从Blob Storage通过Download to Buffer获取PDF出现空白问题求助
问题描述
最初遇到大量错误,首个错误为:Content-Length mismatch: too many bytes written (216523 of 215706)。修复该错误后,PDF可成功下载,但文件内容为空白(原PDF应有内容)。相关代码如下:
let blobUrl = fileUrl; if (!blobUrl) { req.context.log(`Skipping attachment, URL is not yet ready.`, new Date().toString()); return res.status(400).send({ message: 'Attachment is not ready.' }); } else { let sharedKeyCredential = new StorageSharedKeyCredential(utility.dec(client.storageName), utility.dec(client.storageKey)); let blobServiceClient = new BlobServiceClient( `https://${utility.dec(client.storageName)}.blob.core.windows.net`, sharedKeyCredential ); let urlParts = new URL(blobUrl); let pathParts = urlParts.pathname.split('/'); let blobName = pathParts.slice(2).join('/'); let sourceBlob = blobServiceClient.getContainerClient(constants.BLOB_CONTAINER_ATTACHMENT).getBlobClient(blobName); req.context.log('Downloading blob:', blobName); const pdfFile = await sourceBlob.downloadToBuffer({ onProgress: (progress) => { req.context.log(`Downloaded ${progress.loadedBytes} bytes`); } }); res.setHeader('Content-Type', 'application/pdf'); res.setHeader('Content-Disposition', `attachment; filename="${blobName}"`); res.set('Transfer-Encoding', 'identity'); res.send(pdfFile);
解决方案及代码修改
1. 移除Transfer-Encoding手动设置
Express会根据响应内容自动处理Content-Length和编码方式,手动设置Transfer-Encoding: identity会和自动计算的内容长度冲突,既会引发Content-Length mismatch错误,也可能导致内容传输异常。
2. 修正文件名转义问题
Content-Disposition中的文件名使用了HTML实体",这会导致文件名解析异常,应直接使用单引号或正确转义的双引号。
3. 验证Blob内容有效性
在发送响应前添加日志,确认下载的buffer长度,避免因路径解析错误下载了空文件。
修改后的代码
let blobUrl = fileUrl; if (!blobUrl) { req.context.log(`Skipping attachment, URL is not yet ready.`, new Date().toString()); return res.status(400).send({ message: 'Attachment is not ready.' }); } else { let sharedKeyCredential = new StorageSharedKeyCredential(utility.dec(client.storageName), utility.dec(client.storageKey)); let blobServiceClient = new BlobServiceClient( `https://${utility.dec(client.storageName)}.blob.core.windows.net`, sharedKeyCredential ); let urlParts = new URL(blobUrl); let pathParts = urlParts.pathname.split('/'); let blobName = pathParts.slice(2).join('/'); let sourceBlob = blobServiceClient.getContainerClient(constants.BLOB_CONTAINER_ATTACHMENT).getBlobClient(blobName); req.context.log('Downloading blob:', blobName); const pdfFile = await sourceBlob.downloadToBuffer({ onProgress: (progress) => { req.context.log(`Downloaded ${progress.loadedBytes} bytes`); } }); // 验证buffer是否有效 req.context.log(`Downloaded buffer length: ${pdfFile.length}`); if (pdfFile.length === 0) { return res.status(500).send({ message: 'Downloaded blob is empty.' }); } res.setHeader('Content-Type', 'application/pdf'); // 修正文件名转义,使用单引号避免转义问题 res.setHeader('Content-Disposition', `attachment; filename='${blobName}'`); // 移除手动设置的Transfer-Encoding res.send(pdfFile); }
额外排查点
- 确认
blobName解析是否正确:打印blobName值,验证是否和存储中的Blob路径一致,避免因路径错误下载了不存在或空的Blob。 - 检查Azure Blob存储中的目标PDF是否确实有内容:直接在Azure Portal中查看Blob的大小和内容,排除源文件本身为空的可能。
内容的提问来源于stack exchange,提问作者hellblazer
相关产品推荐
相关产品推荐

