能否无需转换为字符串解析multipart/mixed类型HTTP响应?
解决Angular中multipart/mixed响应的解析问题
直接将响应转为text再转回二进制的方式会因UTF-8编码丢失原始字节数据,导致PDF损坏。正确的做法是直接以blob类型接收响应,再基于ArrayBuffer解析multipart内容,全程避免字符串编码转换。
步骤1:以Blob类型接收响应
发起请求时设置responseType: 'blob',同时通过observe: 'response'获取完整响应(包含响应头):
this.http.get('/your-api-endpoint', { responseType: 'blob', observe: 'response' }).subscribe(async (response) => { await this.parseMultipart(response); });
步骤2:解析multipart响应
从响应头提取分隔符,将Blob转为ArrayBuffer后拆分各部分,分别处理JSON和PDF:
async parseMultipart(response: HttpResponse<Blob>) { // 提取multipart分隔符 const contentType = response.headers.get('Content-Type'); const boundaryMatch = contentType?.match(/boundary=(.*)/); if (!boundaryMatch) throw new Error('无法识别multipart分隔符'); const boundary = `--${boundaryMatch[1]}`; // 将Blob转为ArrayBuffer,保留原始二进制数据 const arrayBuffer = await response.arrayBuffer(); const rawContent = new TextDecoder('utf-8').decode(arrayBuffer); // 拆分各部分(过滤空内容和结尾标记) const parts = rawContent.split(boundary).filter(part => part.trim() !== '' && !part.includes('--')); for (const part of parts) { // 拆分每个部分的头信息和内容体 const [headerStr, content] = part.split('\r\n\r\n', 2); const partHeaders = this.parsePartHeaders(headerStr); if (partHeaders['Content-Type'] === 'application/json') { // 解析JSON数据 const jsonData = JSON.parse(content); console.log('解析得到的JSON:', jsonData); } else if (partHeaders['Content-Type'] === 'application/pdf') { // 从原始ArrayBuffer中截取PDF对应的字节(避免字符串转码损失) const contentStartIdx = rawContent.indexOf('\r\n\r\n', rawContent.indexOf(headerStr)) + 4; const contentEndIdx = rawContent.indexOf(boundary, contentStartIdx) - 2; // 减去末尾的\r\n const pdfBuffer = arrayBuffer.slice(contentStartIdx, contentEndIdx); const pdfBlob = new Blob([pdfBuffer], { type: 'application/pdf' }); // 触发PDF下载 const downloadUrl = window.URL.createObjectURL(pdfBlob); const link = document.createElement('a'); link.href = downloadUrl; link.download = 'document.pdf'; link.click(); window.URL.revokeObjectURL(downloadUrl); } } } // 辅助函数:解析multipart单个部分的头信息 parsePartHeaders(headerStr: string): Record<string, string> { const headers: Record<string, string> = {}; headerStr.split('\r\n').filter(line => line.trim()) .forEach(line => { const [key, value] = line.split(': ', 2); headers[key] = value; }); return headers; }
关键说明
- 避免字符串编码转换:直接操作ArrayBuffer可以完整保留PDF的原始字节,不会因UTF-8编码的字符映射丢失或篡改二进制数据
- 精准截取字节:通过原始内容的索引定位PDF在ArrayBuffer中的起止位置,确保生成的Blob与后端返回的PDF字节完全一致
内容的提问来源于stack exchange,提问作者TigersEye120
相关产品推荐
相关产品推荐

