【问题标题】:Why do I get a blank pdf when uploaded on S3?为什么我在 S3 上上传时会得到一个空白的 pdf?
【发布时间】:2021-11-27 12:42:47
【问题描述】:

我将 pdf blob 对象上传到 S3

      const params = {
        Bucket: "poster-print-bucket",
        Key: Date.now().toString() + ".pdf",
        Body: blob,
        contentType: "application/pdf",
      };

      const uploaded = await S3.upload(params).promise();

当我打开一个网址时,即https://poster-print-bucket.s3.ca-central-1.amazonaws.com/1633526785678.pdf 它给我下载了一个空白的pdf

我想我的 blob 可能已损坏或其他原因,但我设法将相同的 blob 上传到 Firebase 存储就好了。

顺便说一句,我正在使用 nextjs api/upload-poster 路由

发生了什么事?

【问题讨论】:

  • 您是否尝试过将 blob 转换为 base64? stackoverflow.com/questions/18650168/convert-blob-to-base64
  • 错误Failed to load PDF document.打开网址时
  • ContentMD5 扔在那里也可以验证它实际上正在上传。您可能还需要try/catch 以确保没有错误并且上传实际上已完成,然后再继续。
  • 我对 ContentMD5 不熟悉。它如何帮助验证它是否已上传?我在我的 S3 存储桶中看到它已上传。文件大小似乎也是我所期望的,但是 pdf 为空白是非常奇怪的

标签: javascript node.js amazon-web-services amazon-s3


【解决方案1】:

我在解决这个问题上花费的时间比我愿意承认的要多。 这是解决方案:

前端(在发送到后端之前将 blob 转换为 base64):

            function toBase64(blob) {
              const reader = new FileReader();
              return new Promise((res, rej) => {
                reader.readAsDataURL(blob);
                reader.onload = function () {
                  res(reader.result);
                };
              });
            }

            toBase64(currentBlob)
              .then((blob) => {
                return axios
                  .post("/api/upload-poster", blob, {
                    headers: {
                      "Content-Type": "application/pdf",
                    },
                  })
                  .then(({ data }) => data.uploaded.Location);
              })

后端:

      const base64 = req.body;
      const base64Data = Buffer.from(base64.replace(/^data:application\/\w+;base64,/, ""), "base64");
     
      const params = {
        Bucket: "poster-print-bucket",
        Key: nanoid() + ".pdf",
        Body: base64Data,
        ContentEncoding: "base64",
        contentType: "application/pdf",
      };

      const uploaded = await S3.upload(params).promise();

为什么所有的歌曲和舞蹈都是必需的?能不能简单点?

【讨论】:

    【解决方案2】:

    使用 AWS SDK v3(在本文发布时为最新版本),您可以使用 PutObjectCommand,它接受 Uint8Array 作为 Body 参数 (docs)。

    将您的 Blob 实例转换为 ArrayBuffer (docs),并将您的 ArrayBuffer 转换为 Uint8Array。

    代码如下:

    const { S3Client, PutObjectCommand } = require('@aws-sdk/client-s3');
    const client = new S3Client(/* config */);
    
    const arrayBuffer = await blob.arrayBuffer();
    const typedArray = new Uint8Array(arrayBuffer);
    await client.send(new PutObjectCommand({
       Bucket: /* ... */,
       Key: /* ... */,
       Body: typedArray,
    }));
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-07
      • 2020-06-04
      • 1970-01-01
      • 2014-12-29
      • 2018-09-03
      • 1970-01-01
      相关资源
      最近更新 更多