POST方法从Blob Storage下载Buffer生成空白PDF求助
问题描述
使用POST方法从Azure Blob Storage下载PDF到Buffer时,先出现Content-Length不匹配错误(写入216523字节,预期215706字节),修复后能成功触发下载,但打开PDF后内容为空白。因隐私要求代码已脱敏,且无法使用pipe(Postman请求耗时过长),寻求可行解决方案。
相关代码
app.post( "/api/**client-endpoint**/download/attachments", async (req, res, next) => { try { let claims = await authentication.authJwtToken(req, req.context); req.context.log("Validated claims: ", JSON.stringify(claims)); let allowedPermissions = [permissionConstants.PERMISSION_ADMIN_CUSTOMER_VIEW]; let auth = await authorization.authorize(req.context, claims, permissionConstants.AUTH_MODE_CLIENT, allowedPermissions, req.body.clientId, undefined, undefined, constants.AUTH_TOKEN_TYPE_ADMIN); let client = await coreClientDao.mssqlGetClientByIdAuthObject(constants.**CLIENTNAME**_CLIENT_ID, req.context); const { clientId, customerId, fileUrl } = req.body; if (!fileUrl) { return res.status(400).send({ message: 'fileUrl is required.' }); } req.context.log("Processing file for clientId: ", clientId); 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); } } catch (error) { utility.catchErrorRespnse(res, req.context, error); } } );
解决方案建议
- 验证Buffer完整性:在
downloadToBuffer后添加日志,打印pdfFile.length,对比Blob存储中目标文件的实际大小。如果长度不匹配,说明下载的Buffer不完整或指向错误文件。 - 修正Blob名称解析:URL路径可能包含编码字符(如空格转
%20),需解码后再拼接Blob名称:let blobName = decodeURIComponent(pathParts.slice(2).join('/')); - 移除强制传输编码设置:注释掉
res.set('Transfer-Encoding', 'identity');,让Express自动处理响应头,避免手动设置导致内容传输异常。 - 确认Blob文件属性:通过
sourceBlob.getProperties()获取文件的contentType,确保存储的PDF文件类型为application/pdf,避免内容格式不匹配。 - 优化下载参数:给
downloadToBuffer添加重试参数,提升下载可靠性:const pdfFile = await sourceBlob.downloadToBuffer({ onProgress: (progress) => { req.context.log(`Downloaded ${progress.loadedBytes} bytes`); }, maxRetryRequests: 3 }); - 替换响应方法:将
res.send(pdfFile)改为res.end(pdfFile),直接输出Buffer,避免Express对内容做额外处理导致损坏。
内容的提问来源于stack exchange,提问作者hellblazer
相关产品推荐
相关产品推荐

