概要
在前端下載檔案是個很通用的需求,一般后端會提供下載的方式有兩種:
- 直接回傳檔案的網路地址(一般用在靜態檔案上,比如圖片以及各種音視瞥澩等)
- 回傳檔案流(一般用在動態檔案上,比如根據前端選擇,匯出不同的統計結果 excel 等)
第一種方式比較簡單,但是使用場景有限,
第二種方式通用性更好,最近再使用 antd 開發的程序中,下載檔案部分折騰了一下午,于是將關鍵的部分和遇到的一些問題整理如下,
前端核心代碼
我的前端是基于 antd pro 開發的,這里不在詳細介紹 antd pro 相關的內容,只說明下封裝的下載函式:
import { request } from "umi";
// 這是我在專案中封裝的下載函式,有2個引數:
// 一個是檔案的id,用來給后端API搜索檔案用的
// 一個是檔案名filename,這個給前端用的,下載時,默認保存的檔案名
export async function DownloadFile(id: string, filename: string) {
return RestGet<BlobPart>(`/api/v1/file/download/${id}`, "blob").then(
(res) => {
let url = URL.createObjectURL(new Blob([res], { type: "octet/stream" }));
let a = document.createElement("a");
a.href = https://www.cnblogs.com/wang_yb/archive/2022/12/02/url;
a.download = filename;
a.click();
URL.revokeObjectURL(url);
}
);
}
// GET 方式請求后端API
export async function RestGet(
url: string,
responseType:"json" | "blob" = "json"
) {
return request<T>(url, {
method: "GET",
headers: {
"Content-Type": "application/json",
},
responseType: responseType,
});
}
// POST 方式請求后端API
export async function RestPost<T>(
url: string,
body: any,
responseType: "json" | "blob" = "json"
) {
return request<T>(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
data: body,
responseType: responseType,
});
}
這個下載函式本質就是創建一個 <a> 元素,然后模擬點擊此 <a> 元素來完成下載,
對于 DownloadFile函式,我是根據自己的需要封裝的,不一定非得是這兩個引數,可以根據自己的后端 API 來定制需要傳入的引數,
將下載封裝成函式之后看,前端就可以通過一個按鈕來下載檔案了,比如:
<Button
type="link"
key="download"
icon={<DownloadOutlined />}
onClick={() =>
DownloadFile(item.video_file_id as string, (item.name as string) + ".mp4")
}
>
下載
</Button>
我這里是 GET 方式下載檔案的,如果引數比較多且復雜的話,也可以使用 POST 方式,
只要把 DownloadFile中 RestGet<T>改成 RestPost<T>,并調整相應的引數即可,
遇到的問題
除錯其中的下載方式就不提了,遇到的最大困難,搜索半天也沒什么人提到的就是請求中的 responseType問題,
剛開始,我沒有設定 responseType,默認值好像是 json或者 text,
測驗時發現,下載文本型別的檔案沒有問題,但是下載二進制檔案的話,比如視頻或者圖片,下載之后總是無法正常打開,前后端也沒有任何錯誤提示,
折騰了半天,才試出 responseType傳入 blob的話,二進制檔案才能正常下載,
而且發現,設定成 blob的話,文本型別的檔案也能正常下載打開,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/539069.html
標籤:其他
