关键词 :Angular13 JavaScript Blob
前言
在项目的实际过程中,需要下载一个大于10MB的文件, Apigee会直接拒绝此次下载。所以后端需要将大于10MB的文件切割成一个个小于8MB的文件,此时前端需要将切割的文件合并成一个文件后再进行下载。
冲突
在解决的过程中,有两个问题冲突:
对于要下载的这个文件,不清楚这个文件的大小,所以不清楚需要执行几次请求去后台请求数据。若简单的通过for循环去重复请求,则会遇到异步问题。这里可以用闭包解决,但是不提倡。
如何将多个Blob文件合并成同一个。
解决方案:
1.用递归去解决循环的问题。(具体实现参考下述完整代码)
2.有两种方式去将Blob拼接
const chunckNumber = ! fileSize ? 1 : Math . ceil ( fileSize / ( 8 * 1024 * 1024 ));
let fileData = [];
const getFileContent = ( index ) => {
if ( index < chunckNumber ) { // chunckNumber 指的是需要循环的次数
getFileContent ( id , true , index ). subscribe ( data => { // getFileContent 是一个 service 请求
fileData . push ( data ); // data 是 blob 属性
getFileContent ( index + 1 );
},
( err ) => {
this . selectFileId = null ;
this . handleError ( err );
});
} else {
this . selectFileId = null ;
const blob = new Blob ( fileData , {
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
});
const link = document . createElement ( 'a' );
link . href = window . URL . createObjectURL ( blob );
link . download = name ;
link . click ();
window . URL . revokeObjectURL ( link . href );
}
};
getFileContent ( 0 );
2.将Blob片段转化为2进制然后合并到一个数组里
const chunckNumber = ! fileSize ? 1 : Math . ceil ( fileSize / ( 8 * 1024 * 1024 ))
let fileData = new Uint8Array ([]);
const getFileContent = ( index ) => {
if ( index < chunckNumber ) { // chunckNumber 指的是需要循环的次数
getFileContent ( id , true , index ). subscribe ( data => { // getFileContent 是一个 service 请求
data . arrayBuffer (). then ( buffer => { // 返回类型为 Blob 的 data
fileData = new Uint8Array ([
... fileData ,
... new Uint8Array ( buffer ),
]);
getFileContentx ( index + 1 );
})
});
} else {
const blob = new Blob ([ fileData ], {
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
});
const link = document . createElement ( 'a' );
link . href = window . URL . createObjectURL ( blob );
link . download = name ;
link . click ();
window . URL . revokeObjectURL ( link . href );
}
};
getFileContent ( 0 );
后言
希望本文会对你有所帮助,如果有什么问题,可在下方留言沟通。