JS透過ajax下載檔案

之前點擊畫面中下載按鈕,透過window.location的方式,與後端串接來進行下載檔案。

1
window.location = download_url

開發案例中,是從DB查詢資料後匯入Excel檔案並下載,但開發時,客戶要求需要能夠過濾出資料,不希望將所有資料都匯出。

因此必須透過傳遞參數的方式來達成此要求。

方法一: 透過ajax先查詢出資料,並暫存FileStreamResult於HashTable中,返回ajax後,再透過window.location去做直接下載的部分。

方法二: 直接透過window.location傳遞參數。

原先寫法為

Test.js
1
window.location = '/ExController/exportExcel';
ExController.cs
1
2
3
4
5
6
7
8
9
10
public ActionResult exportExcel()
{
//取得Excel stream
Stream stream = getDBData();
FileStreamResult fileStreamResult = new FileStreamResult(stream, "application/octet-stream");
fileName = ExcelHelper.TemplateFileName;
fileStreamResult.FileDownloadName = "ExcelFile.xls";

return fileStreamResult;
}

ajax 下載檔案

改寫為透過ajax取得Excel File 資訊。

Test.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
var queryModel = {};
queryModel.keyID = $("#keyId").val();
queryModel.type = $("#type").val();

$.ajax({
type: 'POST',
url: '/ExController/exportExcel',
data: JSON.stringify(queryModel),
contentType: 'application/json; charset=utf-8',
dataType: 'json',
success: function (res) {

}
});

在C#中,命名一個model: RequestModel來傳遞參數。

RequestModel.cs
1
2
3
4
5
6
7
8
9
10
namespace TEST.Models
{
[Serializable]
[DataContract]
public class RequestModel
{
public string KeyID { get; set; }
public string Type { get; set; }
}
}

在原本exportExcel函式中,建立HashTable,並將剛剛的FileStreamResult存放在此HashTable中,等下Download完畢後,再從此HashTable移除。

並將回傳值更改為json格式

ExController.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

private static Hashtable mExcelStreams = new Hashtable();

public ActionResult exportExcel(RequestModel request)
{
//取得Excel stream

Stream stream = getDBData(request);
FileStreamResult fileStreamResult = new FileStreamResult(stream, "application/octet-stream");
fileName = ExcelHelper.TemplateFileName;
fileStreamResult.FileDownloadName = "ExcelFile.xls";

string fuid = Guid.NewGuid().ToString();
mExcelStreams.Add(fuid, fileStreamResult);

return Json(new {
FileGuid = fuid,
FileName = fileName
});;
}

當ajax返回時,透過window.location再次呼叫Controller下載檔案。

Test.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
var queryModel = {};
queryModel.keyID = $("#keyId").val();
queryModel.type = $("#type").val();

$.ajax({
type: 'POST',
url: '/ExController/exportExcel',
data: JSON.stringify(queryModel),
contentType: 'application/json; charset=utf-8',
dataType: 'json',
success: function (res) {
window.location = '/ExController/downloadExcel' + "?fuid=" + res.fileGuid;
}
});

根據uuid來取得剛剛的FileStreamResult並下載。

ExController.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

private static Hashtable mExcelStreams = new Hashtable();

public ActionResult downloadExcel(string fuid)
{
if (mExcelStreams.ContainsKey(fuid))
{
FileStreamResult result = (FileStreamResult)mExcelStreams[fuid];
mExcelStreams.Remove(fuid);
return result;
}
else {
return null;
}
}

window.location 攜帶參數下載檔案

Test.js
1
2
3
4
5
var queryModel = {};
queryModel.keyID = $("#keyId").val();
queryModel.type = $("#type").val();

window.location = '/ExController/exportExcel?request=' + JSON.stringify(queryModel);

在Controller中,先將參術取出後,並解析出json格式資料並轉換為RequestModel。

ExController.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public ActionResult exportExcel()
{
string getval = Request.QueryString["request"];
JObject j_obj = JObject.Parse(getval);
Dictionary<string, string> str_dict = j_obj.ToObject<Dictionary<string, string>>();
RequestModel request = new RequestModel();
request.KeyID = str_dict["keyID"].ToString();
request.Type = str_dict["type"].ToString();

//取得Excel stream
Stream stream = getDBData(request);
FileStreamResult fileStreamResult = new FileStreamResult(stream, "application/octet-stream");
fileName = ExcelHelper.TemplateFileName;
fileStreamResult.FileDownloadName = "ExcelFile.xls";

return fileStreamResult;
}
作者

Nick Lin

發表於

2022-03-04

更新於

2023-01-18

許可協議


評論