我正在尝试使用 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)."
为了澄清这里发生的事情,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/