個人CodeBase紀錄 - EP.3 點我下載! ajax呼叫action回傳檔案流


Posted by Mike.Lin on 2023-08-14

公司專案中,多有需求要查詢報表或作文檔的套印,因此需要在頁面上回傳檔案樓作另開頁面列印或套印檔案的下載,此篇會提及回傳檔案流的擴充方法,以及前端ajax接收檔案流的寫法。


回傳下載檔案流

檔案流擴充

我們可以透過MemoryStream將檔案透過選定格式讀成檔案流

/// <summary>
/// 取得文件匯出的 FileStream
/// </summary>
/// <param name="doc"></param>
/// <param name="saveFormat"></param>
/// <returns></returns>
public static System.IO.MemoryStream GetFileStream(this Document doc, Aspose.Words.SaveFormat saveFormat)
{
    var fileStream = new System.IO.MemoryStream(); // new 檔案流
    doc.Save(fileStream, saveFormat); // 將文檔以saveFormat傳到fileStream
    fileStream.Position = 0; // 將MemoryStream讀取的位置設回開頭
    return fileStream;
}

其中,SaveFormat為Aspose提供的儲存格式,可以選定Aspose提供的枚舉值來設定讀取檔案流的格式

也可以在擴充內透過switch來針對不同的saveformat做不同處理:

/// <summary>
/// 取得文件匯出的 FileStream
/// </summary>
/// <param name="workbook"></param>
/// <param name="saveFormat"></param>
/// <returns></returns>
public static System.IO.MemoryStream GetFileStream(this Workbook workbook, Aspose.Cells.SaveFormat saveFormat)
{
    var fileStream = new System.IO.MemoryStream();

    switch (saveFormat)
    {
        case Aspose.Cells.SaveFormat.Csv:
            var saveOptions = new TxtSaveOptions { Encoding = Encoding.UTF8 };
            workbook.Save(fileStream, saveOptions);
            break;
        default:
            workbook.Save(fileStream, saveFormat);
            break;
    }
    fileStream.Position = 0;
    return fileStream;
}

如此,便可以取得該檔案的檔案流!


回傳檔案流結果

在MVC專案中,也有回傳檔案專用的Result,可以給定檔案流及回傳格式來回傳檔案至前端

/// <summary>
/// 取得doc檔匯出串流
/// </summary>
/// <returns></returns>
public ActionResult ExportDocxFile()
{
    var data = _FakeMultiLayerList.FakeListForBind(); // 假資料

    var doc = new Document("test.docx"); // 開啟範例文檔
    doc.BindData(data); // 透過擴充方法套印檔案 -> 也可做其他檔案操作
    doc.Save("bindedDoc.docx", Aspose.Words.SaveFormat.Docx);
    return File(doc.GetFileStream(Aspose.Words.SaveFormat.Docx), "application/docx"); // 回傳contentType為"application/docx"的檔案流
}

接著在view頁面透過ajax呼叫該action

<script>
// 匯出docx
function ExportDocxFile() {
    $.ajax({
        url: '@Url.Action("ExportDocxFile", "Home")', // 呼叫的url
        type: 'POST',
        xhrFields: {
            responseType: 'blob' // 回傳為二進制的數據
        },
        success: function (response) {
            // 下載部分
            if (response instanceof Blob) { // 若為blob
                var blob = new Blob([response], { type: 'application/octet-stream' }); // 建一個'application/octet-stream'的blob物件來接回傳數據
                // 生臨時url
                var url = URL.createObjectURL(blob); 
                var downloadLink = document.createElement('a'); 
                downloadLink.href = url;
                downloadLink.download = 'Binded.docx'; // 設定下載名稱
                downloadLink.click(); // 自動點擊來做下載
                location.reload();
            }
            else { // 回傳非Blob的其他處理
                ShowMessageBlock("查無!");
            }
        },
        error: function (error) {
            console.log(error);
        }
    });
}
</script>

在前端呼叫該function後,瀏覽器會自動下載符合格式的檔案


回傳檔案html另開頁面套印

回傳html

我們透過Aspose的save將檔案存成html格式,再透過StreamReader將讀取內容存到content,回傳Content Result

/// <summary>
/// 列印
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public ActionResult Print()
{
    var data = _FakeMultiLayerList.FakeListForBind();

    // 開啟範例文檔
    var doc = new Document("test.docx");
    doc.BindData(data);
    doc.Save("bindedDoc.docx", Aspose.Words.SaveFormat.Docx);

    // 如果有資料
    if (doc != null)
    {
        // 轉html字串
        var content = string.Empty;
        // 利用StreamReader將檔案讀成html格式
        using (StreamReader reader = new StreamReader(doc.GetFileStream(Aspose.Words.SaveFormat.Html)))
        {
            content = reader.ReadToEnd(); // 將讀取內容存到content
        }
        return Content(content); // 回傳字串結果
    }
    else
    {
        return Json(new { nodata = true });
    }
}

前端接收html字串另開頁面套印

前端部分,先透過回傳格式來判斷流程,若回字串塞到頁面上hidden的html容器,並透過printpage列印

<script>
// 列印證明冊
    function PrintDocxFile() {
        var url = '@Url.Action("Print", "Home")';
        $.ajax({
            url: url,
            type: 'GET',
            success: function (response) {
                debugger
                if (typeof response === 'string') {
                    $('#PrintContainer').html(response);
                    printpage('PrintContainer');
                }
                else {
                    ShowMessageBlock("查無資料!");
                }
            },
            error: function (error) {
                console.log(error);
            }
        });
    }
</script>

如此便可將檔案顯示在頁面上,或透過jquery使用瀏覽器的列印。


結語

透過GetFileStream的擴充,我們可以針對要回傳的格式作個別的操作。這邊要特別注意ajax接收的格式,要與action回傳的檔案流格式相容。
另外,若在練習時,aspose沒有憑證的狀況,會有浮水印,這會導致doc在做save成html時,因為浮水印圖檔導致報錯,可以透過設定圖檔檔案流選單的設置來避開,後續有機會會再對aspose的眉眉角角開系列><


#.Net Mvc #aspose #ajax







Related Posts

設計API回傳/接收JSON

設計API回傳/接收JSON

樂威壯副作用有哪些?

樂威壯副作用有哪些?

for ...in   for...of   forEach

for ...in for...of forEach


Comments