前端實(shí)現(xiàn)下載文件(包含壓縮包下載)方式詳細(xì)總結(jié)
前言
默認(rèn)最簡(jiǎn)單的下載方式是:window.open(后臺(tái)接口API路徑),但該方法弊端:因是新開窗口方式,前端展示上,每次會(huì)閃下。
此外,如果使用window.open(文件URL)方式:
- pdf、office文檔、psd:直接下載。
- 圖片、txt:新開窗口預(yù)覽,不會(huì)下載;且txt預(yù)覽,有時(shí)出現(xiàn)中文亂碼問題。
一、根據(jù)文件URL下載
實(shí)現(xiàn)原理:通過a標(biāo)簽實(shí)現(xiàn)下載。
/**
* @method 下載單個(gè)文件(文件類型可任意:.png、txt、office文檔、.psd等)
* @param { String } url - 文件的http完整路徑, 如:http: //xxx.png
* @param { String } fileName - 文件名,注意是要帶文件后綴名,如:xxx.png
* @doc https://blog.csdn.net/weixin_39547158/article/details/110851570
*/
export function downloadFile(url: string, fileName: string) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'blob';
xhr.upload.onprogress = (e) => {
if (e.lengthComputable) {
let progress = e.loaded / e.total;
console.log('文件上傳進(jìn)度是', progress);
}
};
xhr.onload = function () {
const url = window.URL.createObjectURL(xhr.response);
const eleLink = document.createElement('a');
eleLink.href = url;
eleLink.download = `${fileName}`;
eleLink.style.display = 'none';
document.body.appendChild(eleLink);
eleLink.click();
document.body.removeChild(eleLink);
resolve('success');
};
xhr.onerror = (e) => {
console.log('請(qǐng)求錯(cuò)誤回調(diào)', e);
message.warning('下載文件失敗')
reject(e);
};
xhr.send();
});
}二、excel文件:調(diào)用后臺(tái)接口返回文件流,前端下載文件
實(shí)現(xiàn)原理:調(diào)用后臺(tái)接口,返回blob, 前端使用file-saver庫(kù)實(shí)現(xiàn)下載。
// 下載excel文件
import { saveAs } from 'file-saver';
const downloadTemplate = async () => {
try {
const params = { ... } // 傳參
const res = await generateDownStreamReconciliationUsingGET(params);
// res為返回結(jié)果
if (res) {
const blob = new Blob([res], { type: 'application/vnd.ms-excel' });
FileSaver.saveAs(blob, '對(duì)賬單.xlsx');
console.log('對(duì)賬單下載成功')
}
} catch (e) {
console.log(e);
} finally {
console.log('finally')
}
};// 生成對(duì)賬excel模板表格API
export async function generateDownStreamReconciliationUsingGET(
params: API.generateDownStreamReconciliationUsingGETParams,
options?: { [key: string]: any },
) {
return request<any>(
`${process.env.APP_HOST_WAYBILL}/xxx/generateDownStreamReconciliation`,
{
method: 'GET',
responseType: 'blob', // 必須寫該行,否則:后臺(tái)返回的是string,不是blob且文件下載后,會(huì)出現(xiàn)打不開問題。
params: {
...params,
},
...(options || {}),
},
);
}三、多文件URL下載,前端生成壓縮包下載
實(shí)現(xiàn)原理:jszip庫(kù) + file-saver庫(kù)
import { getBlobOfUrl } from '@/services/common';
import { saveAs } from 'file-saver';
import JSZip from 'jszip';
import { message } from 'antd';
/**
* @method 同時(shí)下載多文件,并生成一個(gè)壓縮包
* @param { Object[] } fileInfoList - 文件列表
* @param { String } urlField - 文件URL的字段名
* @param { String } fileNameField - 文件名的字段名
* @param { String } folderName - 壓縮包 & 文件夾名稱
*/
export function downloadAsZip(
fileInfoList: any[],
folderName = '文件壓縮包',
urlField = 'filePath',
fileNameField = 'name',
) {
return new Promise((resolve, reject) => {
const zip = new JSZip();
// const folder = zip.folder(folderName); // 創(chuàng)建文件夾
const promisesList = fileInfoList.map((item) => {
return getBlobOfUrl(item[urlField])
.then((data) => {
// console.log(data); // Blob
// folder.file(item[fileNameField], data, { binary: true }); // 往文件夾中存放文件
zip.file(item[fileNameField], data, { binary: true }); // 不創(chuàng)建文件夾
})
.catch((e) => {
console.log(e);
message.warning(e?.message || '獲取文件流失敗')
});
});
Promise.all(promisesList)
.then(() => {
zip
.generateAsync({ type: 'blob' })
.then((content) => {
saveAs(content, folderName);
resolve('success');
})
.catch((e) => {
message.warning(e?.message || '生成壓縮包失敗')
reject(e);
});
})
.catch((e) => {
message.warning(e?.message || '批量獲取文件流失敗')
reject(e);
});
});
}import { request } from 'umi';
/**
* @method 根據(jù)文件URL獲取blob數(shù)據(jù)流的API
* @param { String } fileUrl - 文件完整路徑,如:http://xxx.png
*/
export function getBlobOfUrl(fileUrl: string) {
return request(fileUrl, {
method: 'GET',
responseType: 'blob', // 設(shè)置后臺(tái)返回的內(nèi)容類型為blob
params: {
notAuthorization: true,
},
});
}總結(jié)
到此這篇關(guān)于前端實(shí)現(xiàn)下載文件(包含壓縮包下載)方式的文章就介紹到這了,更多相關(guān)前端實(shí)現(xiàn)下載文件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Javascript中對(duì)象繼承的實(shí)現(xiàn)小例
這篇文章主要介紹了Javascript中對(duì)象繼承的實(shí)現(xiàn),需要的朋友可以參考下2014-05-05
JavaScript字符串操作的四個(gè)實(shí)用技巧
在制作前端頁(yè)面的過程中,經(jīng)常需要用到JavaScript進(jìn)行邏輯處理,很多時(shí)候都需要對(duì)字符串進(jìn)行操作,這篇文章主要給大家介紹了關(guān)于JavaScript字符串操作的四個(gè)實(shí)用技巧,需要的朋友可以參考下2021-07-07
JS常用插件之Swiper插件實(shí)現(xiàn)輪播圖功能實(shí)例
項(xiàng)目中會(huì)多次使用到輪播圖組件,下面這篇文章主要給大家介紹了關(guān)于JS常用插件之Swiper插件實(shí)現(xiàn)輪播圖功能的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-07-07
微信小程序獲取用戶手機(jī)號(hào)碼詳細(xì)教程(前端+后端)
在我們開發(fā)微信小程序時(shí),獲取用戶手機(jī)號(hào)碼是常見的需求之一,這篇文章主要給大家介紹了關(guān)于微信小程序獲取用戶手機(jī)號(hào)碼的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下2024-02-02
妙用緩存調(diào)用鏈實(shí)現(xiàn)JS方法的重載
方法重載是指在一個(gè)類中定義多個(gè)同名的方法,但要求每個(gè)方法具有不同的參數(shù)的類型或參數(shù)的個(gè)數(shù)。簡(jiǎn)而言之就是:方法重載就是方法名稱重復(fù),加載參數(shù)不同2018-04-04
Javascript模仿淘寶信用評(píng)價(jià)實(shí)例(附源碼)
這篇文章主要介紹了Javascript模仿淘寶信用評(píng)價(jià)功能實(shí)現(xiàn)方法,以完整實(shí)例形式分析了JavaScript響應(yīng)鼠標(biāo)事件動(dòng)態(tài)改變頁(yè)面元素的相關(guān)技巧,并附帶了完整的實(shí)例代碼供讀者下載參考,需要的朋友可以參考下2015-11-11

