场景:一般下载功能前端使用get请求的方式传参,采用window.open(url)来实现下载。
对于参数比较多的时候,采用post的传参方式,同时后端的返回是二进制的数据流,这个时候我们需要对后端的返回数据进行blob对象的处理,转化成正常的数据,然后实现下载。
后端的返回结果如下:
此时在页面直接调用下载的方法,下载方法如下:
previewDocument = query => {
const lastQuery = { ...query }; // 使用浅拷贝保证多个参数的情况
lastQuery.currency = 'CNY';
if (lastQuery.relatedDocumentId) {
lastQuery.contractWordId = query.relatedDocumentId;
} else {
const wordType = [0, 0, 0];
_.each(lastQuery.wordType, item => {
if (item === '1') {
wordType[0] = 1;
}
if (item === '2') {
wordType[1] = 1;
}
if (item === '3') {
wordType[2] = 1;
}
});
lastQuery.contractWordType = _.join(wordType, '');
}
delete lastQuery.relatedDocument;
delete lastQuery.wordType;
delete lastQuery.relatedDocumentId;
const action = `${window.location.origin}/galaxy/webapi/galaxy/libraSett/previewGoldLeaseContractDocument`;
const api = apiCreator();
// 调用api里面封装好的postDownload方法,将参数和方法传到方法里
api.postDownload(action, lastQuery, '', this.filenameError);
};
filenameError = () => { // 对后端返回文件不存在的情况做处理
message.error('文件名不存在,下载预览失败!');
};
在api中,postDownload方法如下所示:
postDownload(url, query, defaultFilename, errorHandler) {
const finalUrl = padPrefix(url);
const headers = this.getHeaders({
...authInfo,
'Content-Type': 'application/json',
langCode: this.langCode(),
});
return requestPostDownload( // 调用工具类中的requestPostDownload方法
finalUrl,
{
method: 'POST',
headers,
body: JSON.stringify(query),
},
defaultFilename,
errorHandler
);
},
requestPostDownload方法如下所示:
export default function request(url, options, defaultFilename, errorHandler) {
let filename = '';
return Promise.race([
fetch(url, { credentials: 'include', ...options })
.then(response => {
const disposition = response.headers && response.headers.get('content-disposition');
filename =
disposition && disposition.indexOf('=') > -1
? decodeURI(disposition.substring(disposition.indexOf('=') + 1))
: defaultFilename;
if (!defaultFilename && !filename) {
throw new Error('文件名不存在');
} else {
return response.blob();
}
})
.then(blob => {
const objectUrl = URL.createObjectURL(blob);
let downloadLink = document.getElementById('downloadLink');
if (!downloadLink) {
downloadLink = document.createElement('a');
downloadLink.setAttribute('id', 'downloadLink');
downloadLink.setAttribute('style', 'display:none');
document.body.appendChild(downloadLink);
}
downloadLink.setAttribute('download', filename);
downloadLink.setAttribute('href', objectUrl);
downloadLink.click();
URL.revokeObjectURL(objectUrl);
return blob;
})
.catch(error => {
if (errorHandler) {
errorHandler(error);
}
}),
new Promise((rosolve, reject) => {
// eslint-disable-line
setTimeout(
// () => reject('请求超时'),
config.timeout
);
}),
]);
}
综上所述,即可完成post方式的同时后端返回二进制数据流处理的下载功能。