You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 14:07:19