Angular/TypeScript如何处理后端返回的ByteArray列表并渲染图片
问题原因
你的代码存在两个核心错误:
- 原单个文件请求时你显式指定了
responseType: 'arraybuffer'让HttpClient把响应当成二进制处理,改成列表请求后你去掉了这个配置,默认会按JSON解析响应。如果后端返回的是序列化后的字节数组,前端拿到的会是普通数字数组,直接传入Blob构造函数会被当成字符串处理,生成的二进制内容完全错误。 - 新标签页写入HTML后没有调用
document.close(),会导致文档处于加载中状态,部分浏览器无法正常渲染资源。
解决方案
情况1:后端返回JSON格式的数字数组列表
如果后端把每个图片的ByteArray序列化成了JSON数字数组,修改downloadDoc方法如下:
// 注意:Angular 6+ 请使用pipe操作符,需要先导入 import { map } from 'rxjs/operators' downloadDoc(correlationId: string): Observable<Blob[]> { return this.httpClient .get<number[][]>('/rest/someUrl/' + correlationId) .pipe( map(results => results.map(result => { // 先把普通数字数组转成Uint8Array二进制数组 const uint8Array = new Uint8Array(result); return new Blob([uint8Array], { type: "image/png" }); }) ) ); }
情况2:后端返回Base64字符串列表(更推荐)
如果后端把ByteArray转成了Base64字符串返回,可以直接用Data URI展示,不需要生成Blob,性能更高:
downloadDoc(correlationId: string): Observable<string[]> { return this.httpClient .get<string[]>('/rest/someUrl/' + correlationId); }
修改弹窗逻辑
统一调整弹窗代码,增加弹窗拦截判断和文档关闭逻辑:
openDocument() { this.pngService.downloadDoc(correlationId).subscribe(results => { const tab = window.open("", '_blank'); // 处理浏览器拦截弹窗的情况 if (!tab) { alert('请允许浏览器打开弹出窗口后重试'); return; } let htmlStr = "<html><body style='margin: 10px;'>"; results.forEach(item => { let src: string; // 适配Blob和Base64两种返回 if (item instanceof Blob) { src = URL.createObjectURL(item); } else { src = `data:image/png;base64,${item}`; } // 增加img样式避免溢出屏幕 htmlStr += `<img src="${src}" style="max-width: 100%; display: block; margin-bottom: 15px;">`; }); htmlStr += "</body></html>"; tab.document.write(htmlStr); // 必须调用close结束写入,触发浏览器渲染 tab.document.close(); }); }
内容的提问来源于stack exchange,提问作者Catalin
相关产品推荐
相关产品推荐

