简体   繁体   English

来自浏览器JS SDK的AWS S3 multipart / uploadPart静默失败

[英]AWS S3 multipart / uploadPart silent fail from browser JS SDK

I'm trying a multipart s3 upload from the browser with the JS SDK. 我正在尝试使用JS SDK从浏览器进行多部分s3上传。 I have no trouble with createMultipartUpload, but I get no data back from uploadPart. 我对createMultipartUpload没问题,但是我没有从uploadPart返回任何数据。 I can't call completeMultipartUpload because I don't get any eTags back. 我无法调用completeMultipartUpload,因为我没有收回任何eTag。 I get the $response part of the object only, which indicates a 200 status and that all the parameters I passed were defined and the proper datatypes. 我仅获得对象的$ response部分,它指示200状态,并且定义了我传递的所有参数和正确的数据类型。 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. 我看不到存储桶中的任何零件,尽管我不知道它们是否要进入我无法访问的特殊“零件”位置。

Here's my code: 这是我的代码:

    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 instance looks like this: 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
    }
  })

chunker function looks like this: 块函数如下所示:

  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);
  }

The response object I'm getting back looks like this: 我返回的响应对象如下所示:

    (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)

Any ideas? 有任何想法吗? This is in React and my test file is 9.xx MB. 这在React中,我的测试文件是9.xx MB。 I also tried with callbacks, and uploading one part at a time, and got the same thing. 我还尝试了回调,并且一次上传了一部分,并且得到了相同的结果。

In a cross-origin context, you'd need this in your bucket's CORS configuration: 在跨域上下文中,您需要在存储桶的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)." ExposeHeader —标识响应标头……客户将能够从其应用程序(例如,从JavaScript XMLHttpRequest对象)访问该响应标头。”

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

To clarify what's going in here, CORS isn't an access restriction mechanism -- it's a mechanism for giving the browser permission to do something that it otherwise assumes might not be something the user would want to happen. 为了阐明这里发生的情况,CORS不是访问限制机制,而是一种机制,用于授予浏览器执行某些操作的权限,否则该操作可能会假定用户可能不想执行此操作。 It tells the browser to give JavaScript permission to do and see things that would not otherwise be allowed. 它告诉浏览器授予JavaScript权限来执行操作,并查看原本不允许的操作。

From the Mozilla CORS documentation: 从Mozilla CORS文档中:

By default, only the 6 simple response headers are exposed: 默认情况下,仅公开6个简单响应头:

Cache-Control Content-Language Content-Type Expires Last-Modified Pragma 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. 如果希望客户端能够访问其他标头,则必须使用Access-Control-Expose-Headers标头列出它们。

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

In S3, the way you set the Access-Control-Expose-Headers response header is by configuring <ExposeHeaders> (above). 在S3中,设置Access-Control-Expose-Headers响应标头的方式是通过配置<ExposeHeaders> (如上)。 Otherwise, JavaScript can't see them. 否则,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. 我看不到存储桶中的任何零件,尽管我不知道它们是否要进入我无法访问的特殊“零件”位置。

They are. 他们是。 Use the listMultipartUploads to find abandoned uploads, and abortMultipartUploads to delete partial uploads and free the allocated storage space for the parts you uploaded. 使用listMultipartUploads查找废弃的上载,并使用abortMultipartUploads删除部分上载并释放为上载的零件分配的存储空间。 Otherwise, uploads you don't complete will linger indefinitely and you'll be billed for storage of the parts. 否则,您未完成的上传将无限期地徘徊,并且您将需要为存储部分付费。 Also, you can create a bucket lifecycle policy to dispose of them automatically after so many days -- almost always a good idea. 此外,您可以创建存储桶生命周期策略,以便在这么多天后自动处理它们-几乎总是一个好主意。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM