ASP.NET MVC 4 上傳檔案預覽-以Excel為例採用LinqToExcel

  • 1325
  • 0
  • MVC
  • 2018-03-18

很久沒有發文章了,前陣子一堆雜事繁瑣著。

接下來介紹的是我最近寫到EXCEL檔案上傳並要解析預覽的一個小功能。

本篇引用了以下文章內容:

ASP.NET MVC 匯入 Excel 簡單做 - Part.1 檔案上傳

LinqToExcel-GitHub

更新-專案程式碼檔案GitHub - Link

 

首先在做這個練習前我們要確認一下使用了那些第三方套件,以及環境的確認。

jQuery & Bootstrap 

有另外新增的是:

1.Jasny Bootstrap

2.LinqToExcel-GitHub

在LinqToExcel之下需要確認是否有安裝

LinqToExcel說明文件下有提到,必須安裝 Microsoft Access Database Engine 2010 Redistributable否則會造成以下錯誤:

The 'Microsoft.ACE.OLEDB.12.0' provider is not registered on the local machine.'

先分享一個我在這遇到的神奇的問題,首先我在開發時採用了Visual Studio 2012 並且使用.Net FreamWrok 4.0為開發基底。

在本機端的IIS EXPRESS上執行專案的時候一切都正常。

當放到測試伺服器的時候採用IIS7.0執行的時候發生嚴重錯誤,並且IIS將應用程式集區直接自動停用,真是嚇死寶寶了。

而在製作本篇文章的時候,我採用的是Visual Studio 2017 .Net FreamWrok 4.5一直行就才有報出官方文件提到的錯誤訊息,害我當時找不到原因的時候整整傷腦筋了很久。還好最後有找到對的方向。

好啦廢話到此結束,開始我們的正文。

首先整個專案會有以下:

Controller

-HomeController -->小練習不拆架構全部塞裡面

Model

-UserList

View

-Index 

-_Upload ->部分檢視

-_PreviewData->部分檢視

先從前端的HTML部分介紹起

<button class="btn btn-primary btn-lg" data-toggle="modal" data-target="#UploadModal">
    UpLoad
</button>

@Html.Partial("_Upload")

主畫面就長這樣一個上傳檔案的按鈕,功能就是呼叫開啟Bootstrap Moda,另外將部分參照的頁面_Upload參照近來。

<!-- UploadModal -->
<div class="modal fade" id="UploadModal" tabindex="-1" role="dialog" aria-labelledby="UploadModalLabel" aria-hidden="true">
        <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-header">
                    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
                    <h4 class="modal-title" id="UploadModalLabel">檔案上傳</h4>
                </div>
                <div class="modal-body">

                    <div class="fileinput fileinput-new input-group" data-provides="fileinput">
                        <div class="form-control" data-trigger="fileinput">
                            <i class="glyphicon glyphicon-file fileinput-exists"></i>
                            <span class="fileinput-filename"></span>
                        </div>
                        <span class="input-group-addon btn btn-default btn-file">
                            <span class="fileinput-new">選擇檔案</span>
                            <span class="fileinput-exists">更換檔案</span>
                            <input type="file" name="file" id="file" />
                        </span>
                        <a href="#" class="input-group-addon btn btn-default fileinput-exists" data-dismiss="fileinput">移除檔案</a>
                    </div>
                </div>
                <div class="modal-footer">
                    <input type="button" id="ButtonCancel" class="btn btn-default" data-dismiss="modal" value="取消">
                    <input type="button" id="ButtonSubmit" name="ButtonSubmit" class="btn btn-primary" value="上傳檔案">
                </div>
            </div>
        </div>
</div>

<!-- Modal -->
<div class="modal fade" id="PreviewModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">&times;</span>
                </button>
            </div>
            <div class="modal-body">
                <div id="PreviewData"></div>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
                <button type="button" class="btn btn-primary">Save changes</button>
            </div>
        </div>
    </div>
</div>

這部分就只是放了兩個MODAL近來,比較特別的地方是<div id="PreviewData"></div>在第二個MODAL,是用來接收預覽資料用的區塊。

_PreviewData最後一個頁面放預覽資料用的程式碼如下沒什麼好介紹的。

@model IEnumerable<UploadExcelSimple.Models.UserList>


<table class="table">
    <thead>
        <tr>
            <th>
                User ID
            </th>
            <th>
                User Name
            </th>
        </tr>
    </thead>
    <tbody>
        @foreach (var item in Model)
        {
            <tr>
                <td>
                   @item.ID
                </td>
                <td>
                    @item.Name
                </td>
            </tr>

        }
    </tbody>

</table>

接下來是重點的開始從Controller部分開始講起

這部分有分為兩個Action皆為Post才會執行的區段。

[HttpPost]
public ActionResult UpLoad()
 {
  var file = Request.Files as HttpFileCollectionBase;

  var uploadResult = this.FileUploadHandler(file[0]);

  if (uploadResult != null)
  {
     var DataList =  ExcelPreview(uploadResult);
     ViewData.Model = DataList;
  }

    return PartialView("_PreviewData");
}

首先檔案處理的方法在前面引用的第一篇文章中有前輩介紹到 (FileUploadHandler),不過我有稍微修改過。之後會將檔案放在GITHUB給大家參考。

接收完檔案後,透過LinqToExcel進行解析,將解析完的資料存在MODAL並回傳給_PreviewData.cshtml。

解析Excel的片段如下:

 public IEnumerable<UserList> ExcelPreview(string filename)
 {
  var excelFile = new ExcelQueryFactory(filename); //檔案給LINQTOEXCEL函數準備解析

  var targetSheetName = ""; 
  var workSheetNames = excelFile.GetWorksheetNames(); //抓取工作表序列
  foreach (var item in workSheetNames)
   {
     targetSheetName = item;
     break;
   }
            
  var List = excelFile.Worksheet<UserList>(targetSheetName).ToList(); //將讀出的資料對應至MODAL並轉存成LIST
            
  return List;
}

最後其實也是比較複雜一點的就是前端的接收,是透過jQuery ajax的方式進行處理。

<script>

    $('#ButtonSubmit').click(function () {

        var ActionUrl = '@Url.Action("Upload","Home")' //Action位置
        var data = new FormData(); //宣告資料FormData型態要來存檔案資訊用的。
        var files = $("#file").get(0).files;
        data.append(files[0].name, files[0]);

        $.ajax(
            {
              type: "POST",
              url: ActionUrl,
              contentType: false,         // 告诉jQuery不要去這置Content-Type
              processData: false,         // 告诉jQuery不要去處理發送的數據
              data: data
            }).done(function (result)
            {
                $('#PreviewData').html(result);
                $("#PreviewModal").modal()
            })
    });



</script>

上面有一個地方沒解釋道的就是$('#PreviewData').html(result);

這段是將ajax執行完畢後取得回來的Html碼寫入前面有說道的第二個Modal要放資料呈現的<div id="PreviewData"></div>這個部分。

以下就是整段程式跑出來的結果:

上傳檔案

預覽資料

打完收工,新手發文如有誤麻煩請用力指教,謝謝。