javascript - AWS S3 multipart/uploadPart 浏览器 JS SDK 静默失败

标签 javascript amazon-s3

我正在尝试使用 JS SDK 从浏览器进行分段 s3 上传。我对 createMultipartUpload 没有任何问题,但我没有从 uploadPart 获取任何数据。我无法调用completeMultipartUpload,因为我没有收到任何电子标签。我只得到对象的 $response 部分,它指示 200 状态,并且我传递的所有参数都已定义以及正确的数据类型。我看不到桶中的任何零件,尽管我不知道它们是否会去往我无法访问的特殊“零件”位置。

这是我的代码:

    const createParams = {
      Bucket,
      Key: `${uuid()}.${getExtension(file.type)}`,
      ContentType: file.type,
      ContentDisposition: 'attachment'
    }
    return s3.createMultipartUpload(createParams).promise()
    .then(result => {
      console.log(result);
      console.log('chunking...')
      let chunkArr = chunker(file);
      let chunkMap = Promise.map(chunkArr, (chunk, index) => {
        const chunkParams = {
          Body: chunk,
          Bucket: result.Bucket,
          Key: result.Key,
          PartNumber: index + 1,
          UploadId: result.UploadId,
          ContentLength: chunk.size
        }
        console.log(chunkParams)
        return s3.uploadPart(chunkParams).promise();
      });
      return Promise.all(chunkMap);
    })
    .then(result => {
      console.log(result);
      return Promise.resolve(true)
      // let stopParams = {
      //
      // }
      // return s3.completeMultipartUpload(stopParams).promise();
    })
    .catch(err => {
      throw err;
      return Promise.reject(err);
    });

s3 实例如下所示:

import AWS from 'aws-sdk';
AWS.config.setPromisesDependency(Promise);

const s3 = new AWS.S3({
    apiVersion: '2006-03-01',
    accessKeyId: credentials.credentials.AccessKeyId,
    secretAccessKey: credentials.credentials.SecretAccessKey,
    sessionToken: credentials.credentials.SessionToken,
    sslEnabled: true,
    s3ForcePathStyle: true,
    httpOptions: {
      xhrAsync: true,
      xhrWithCredentials: true
    }
  })

分块函数如下所示:

  const chunkFile = (file) => {
    console.log(typeof(file));
    const fileSize = file.size;
    const chunkSize = 5242881; // bytes
    let offset = 0;
    let chunkArr = [];

    const chunkReaderBlock = (_offset, _file) => {
      console.log(_offset);

      if (_offset >= fileSize) {
        console.log("Done reading file");
        return chunkArr;
      }

      let blob = _file.slice(_offset, chunkSize + _offset);
      console.log(blob);
      console.log(typeof(blob));
      chunkArr.push(blob);
      return chunkReaderBlock(chunkSize + _offset, _file);
    }

    return chunkReaderBlock(offset, file);
  }

我返回的响应对象如下所示:

    (2)[{…}, {…}] 

0: {
  $response: Response
}

1: $response: Response 
  cfId: undefined 
  data: {
    $response: Response
  }
  error: null 
  extendedRequestId: undefined 
  httpResponse: HttpResponse 
    body: Uint8Array[] 
    headers: {}
    statusCode: 200 
    statusMessage: "OK"
    stream: EventEmitter {
      _events: {…},
      _maxListeners: undefined,
      statusCode: 200,
      headers: {…}
    }
    streaming: false 
    _abortCallback: ƒ callNextListener(err) __proto__: Object 
    maxRedirects: 10 
    maxRetries: 3 
    redirectCount: 0 
    request: Request {
      domain: undefined,
      service: f… s.constructor,
      operation: "uploadPart",
      params: {…},
      httpRequest: HttpRequest,
      …
    }
  retryCount: 0 
  __proto__: Object 
  __proto__: Object 
 length: 2 
__proto__: Array(0)

有什么想法吗?这是在 React 中,我的测试文件是 9.xx MB。我还尝试使用回调,一次上传一部分,得到了同样的结果。

最佳答案

在跨源上下文中,您需要在存储桶的 CORS 配置中进行此设置:

<ExposeHeader>ETag</ExposeHeader>

ExposeHeader — Identifies the response headers ... that customers will be able to access from their applications (for example, from a JavaScript XMLHttpRequest object)."

https://docs.aws.amazon.com/AmazonS3/latest/dev/cors.html

为了澄清这里发生的事情,CORS 不是一种访问限制机制 - 它是一种允许浏览器执行某些操作的机制,否则浏览器可能认为这不是用户希望发生的操作。它告诉浏览器授予 JavaScript 权限来执行和查看原本不允许的操作。

来自 Mozilla CORS 文档:

By default, only the 6 simple response headers are exposed:

Cache-Control Content-Language Content-Type Expires Last-Modified Pragma

If you want clients to be able to access other headers, you have to list them using the Access-Control-Expose-Headers header.

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers

在 S3 中,设置 Access-Control-Expose-Headers 的方式响应头是通过配置 <ExposeHeaders> (多于)。否则,JavaScript 无法看到它们。

<小时/>

I can't see any of the parts in my bucket, although I don't know if they're going to a special "parts" place that I can't access.

他们是。使用listMultipartUploads查找废弃的上传,以及abortMultipartUploads删除部分上传并释放为您上传的部分分配的存储空间。否则,您未完成的上传将无限期地停留,并且您将需要支付部分存储费用。此外,您还可以创建 bucket lifecycle policy在这么多天后自动处理掉它们——几乎总是一个好主意。

关于javascript - AWS S3 multipart/uploadPart 浏览器 JS SDK 静默失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49122490/

相关文章:

javascript - 在链接点击时在屏幕上显示消息,直到重定向

javascript - 加载 angularJs Controller

java - 使用 S3 DeleteObject 仅删除文件,保持目录结构不变

ubuntu - 从 url 检索图像,然后每分钟将时间戳重命名为本地文件夹

hadoop - AWS EMR Hive 分区无法识别任何类型的分区

javascript - 使用 sql.js 在 HTML 页面中显示 SQLite .db

javascript - JavaScript 中的范围(我认为?!)挑战

javascript - 在重新加载另一个 html 页面后关闭 iframe

php - Amazon SQS 不断返回 403 错误

amazon-web-services - Amazon S3存储桶策略,仅允许一个域访问文件