从AWS服务器获取二进制文件转Uint8Array后长度异常求助
问题:从AWS获取二进制文件后,Uint8Array长度远大于返回的Content-Length?
我用以下TypeScript代码通过CapacitorHttp从AWS服务器获取二进制文件:
export const fetchBinaryFile = async(url: string): Promise<Uint8Array> => { try { const options: HttpOptions = { url, responseType: 'blob' }; const response: HttpResponse = await CapacitorHttp.request(options); if (!response.data) { throw new Error('Failed to fetch binary file'); } const blob = new Blob([response.data]); const arrayBuffer = await readBlobAsArrayBuffer(blob); const uint8Array = new Uint8Array(arrayBuffer); return uint8Array; } catch (error: any) { throw new Error(`Error: ${error.message}`); } }; export const readBlobAsArrayBuffer = (blob: Blob): Promise<ArrayBuffer> => { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.onloadend = () => { if (reader.readyState === FileReader.DONE) { console.log('resolve', reader.result); resolve(reader.result as ArrayBuffer); } }; reader.onerror = reject; reader.readAsArrayBuffer(blob); }); };
请求返回的Content-Length是27852字节,但转换后的Uint8Array长度变成了37625字节,远大于原长度。我猜测是FileReader添加了元数据,但不确定原因,求解答。
原因分析
问题不是FileReader添加元数据,而是你错误地重新创建了Blob对象:
当你设置responseType: 'blob'时,CapacitorHttp返回的response.data本身已经是一个Blob实例。但你用new Blob([response.data])把它放进数组创建新Blob时,JavaScript会把数组里的Blob对象转换成UTF-8编码的字符串(因为Blob构造函数处理非二进制类型的参数时会默认按字符串处理),这个转换过程会破坏原二进制数据,导致长度膨胀。
解决方案
方案1:直接使用返回的Blob,无需重新创建
去掉多余的new Blob([response.data])步骤,直接用response.data作为Blob:
export const fetchBinaryFile = async(url: string): Promise<Uint8Array> => { try { const options: HttpOptions = { url, responseType: 'blob' }; const response: HttpResponse = await CapacitorHttp.request(options); if (!response.data) { throw new Error('Failed to fetch binary file'); } // 直接使用返回的Blob,不用重新创建 const arrayBuffer = await readBlobAsArrayBuffer(response.data as Blob); const uint8Array = new Uint8Array(arrayBuffer); return uint8Array; } catch (error: any) { throw new Error(`Error: ${error.message}`); } };
方案2:用Blob原生的arrayBuffer()方法替代FileReader
现代浏览器/环境中的Blob已经内置了arrayBuffer()方法,无需自己封装FileReader逻辑,代码更简洁:
export const fetchBinaryFile = async(url: string): Promise<Uint8Array> => { try { const options: HttpOptions = { url, responseType: 'blob' }; const response: HttpResponse = await CapacitorHttp.request(options); if (!response.data) { throw new Error('Failed to fetch binary file'); } // 直接调用Blob的arrayBuffer()方法 const arrayBuffer = await (response.data as Blob).arrayBuffer(); return new Uint8Array(arrayBuffer); } catch (error: any) { throw new Error(`Error: ${error.message}`); } };
这样处理后,Uint8Array的长度就会和Content-Length一致了。
内容的提问来源于stack exchange,提问作者edds
相关产品推荐
相关产品推荐

