我有几个lambda函数,可以将多部分上传到Amazon S3存储桶。它们负责创建多部分上传,然后为每个部分上传创建另一个,最后一个用于完成上传。
前两个似乎工作正常(它们以statusCode 200响应),但最后一个失败了。在Cloudwatch上,我可以看到一个错误,说“您建议的上传小于允许的最小大小”。
事实并非如此,因为我上传的文件大于文档上指定的最小大小5Mb。但是,我认为问题发生在每个部分上传中。
为什么?因为每个部分只有2Mb的数据。在docs上,我可以看到除了最后一部分之外的所有部分都需要至少5Mb的大小。然而,当我试图上传大于2Mb的部分时,我得到一个CORS错误,很可能是因为我已经超过了6Mb的有效载荷限制。
有人能帮我吗?下面我留下了我的客户端代码,以防你能看到任何错误。
setLoading(true);
const file = files[0];
const size = 2000000;
const extension = file.name.substring(file.name.lastIndexOf('.'));
try {
const multiStartResponse = await startMultiPartUpload({ fileType: extension });
console.log(multiStartResponse);
let part = 1;
let parts = [];
/* eslint-disable no-await-in-loop */
for (let start = 0; start < file.size; start += size) {
const chunk = file.slice(start, start + size + 1);
const textChunk = await chunk.text();
const partResponse = await uploadPart({
file: textChunk,
fileKey: multiStartResponse.data.Key,
partNumber: part,
uploadId: multiStartResponse.data.UploadId,
});
console.log(partResponse);
parts.push({ ETag: partResponse.data.ETag, PartNumber: part });
part++;
}
/* eslint-enable no-await-in-loop */
const completeResponse = await completeMultiPartUpload({
fileKey: multiStartResponse.data.Key,
uploadId: multiStartResponse.data.UploadId,
parts,
});
console.log(completeResponse);
} catch (e) {
console.log(e);
} finally {
setLoading(false);
}
似乎通过 lambda 上传部件根本不可能,因此我们需要使用不同的方法。
现在,我们的启动多部分上传 lambda 不仅返回一个上传 ID,还返回一堆签名的 URL,这些签名 URL 是使用 S3 aws 开发工具包类生成的,使用 getSignedUrlPromise 方法和“上传分段”作为操作,如下所示:
const getSignedPartURL = (bucket, fileKey, uploadId, partNumber) =>
s3.getSignedUrlPromise('uploadPart', { Bucket: bucket, Key: fileKey, UploadId:
uploadId, PartNumber: partNumber })
此外,由于以这种方式上传一个部件不会返回ETag(或者可能会返回,但我就是无法实现),我们需要在上传每个部件后调用S3类上的listParts方法,以获取这些ETag。我将在下面留下我的反应代码:
const uploadPart = async (url, data) => {
try {
// return await uploadPartToS3(url, data);
return fetch(url, {
method: 'PUT',
body: data,
}).then((e) => e.body);
} catch (e) {
console.error(e);
throw new Error('Unknown error');
}
};
// If file is bigger than 50Mb then perform a multi part upload
const uploadMultiPart = async ({ name, size, originFileObj },
updateUploadingMedia) => {
// chunk size determines each part size. This needs to be > 5Mb
const chunkSize = 60000000;
let chunkStart = 0;
const extension = name.substring(name.lastIndexOf('.'));
const partsQuan = Math.ceil(size / chunkSize);
// Start multi part upload. This returns both uploadId and signed urls for each
part.
const startResponse = await startMultiPartUpload({
fileType: extension,
chunksQuan: partsQuan,
});
console.log('start response: ', startResponse);
const {
signedURLs,
startUploadResponse: { Key, UploadId },
} = startResponse.data;
try {
let promises = [];
/* eslint-disable no-await-in-loop */
for (let i = 0; i < partsQuan; i++) {
// Split file into parts and upload each one to it's signed url
const chunk = await originFileObj.slice(chunkStart, chunkStart +
chunkSize).arrayBuffer();
chunkStart += chunkSize;
promises.push(uploadPart(signedURLs[i], chunk));
if (promises.length === 5) {
await Promise.all(promises);
promises = [];
}
console.log('UPLOAD PART RESPONSE', uploadResponse);
}
/* eslint-enable no-await-in-loop */
// wait until every part is uploaded
await allProgress({ promises, name }, (media) => {
updateUploadingMedia(media);
});
// Get parts list to build complete request (each upload does not retrieve ETag)
const partsList = await listParts({
fileKey: Key,
uploadId: UploadId,
});
// build parts object for complete upload
const completeParts = partsList.data.Parts.map(({ PartNumber, ETag }) => ({
ETag,
PartNumber,
}));
// Complete multi part upload
completeMultiPartUpload({
fileKey: Key,
uploadId: UploadId,
parts: completeParts,
});
return Key;
} catch (e) {
console.error('ERROR', e);
const abortResponse = await abortUpload({
fileKey: Key,
uploadId: UploadId,
});
console.error(abortResponse);
}
};
抱歉,我已经尽我所能一行一行地更正了。
一些注意事项:
-我们使用60Mb块,因为我们的后端花了太长时间为大文件生成所有这些签名的url。
- 此外,此解决方案旨在上传非常大的文件,这就是为什么我们等待每5个部分。
但是,我们面临着上传大文件(约35gb)的问题,因为在上传100/120个片段后,fetch请求突然开始失败,并且没有更多的片段上传。如果有人知道发生了什么,那将是惊人的。我发布这个作为答案,因为我认为大多数人会发现这非常有用。
我正在尝试使用放心的分段上传方法上传csv文件。在 swagger API 文档中,请求正文如下所示,用于分段 csv 上传。 我的代码是这样的。 这在IntelliJ的想法中工作,没有任何问题。但是,当我使用maven将代码打包到jar中并运行它时,它会返回fileNotes异常。 如我所见,唯一的解决方案是使用java文件input stream,但既然swagger说要使用文件,那就不可能使
我正在尝试使用 AWS PHP 开发工具包将一个 30 GB 的文件上传到亚马逊 S3。 它适用于最大7GB的文件。上传30 GB文件时,脚本运行约2小时后,我收到以下错误: 将部件上载到多部件上载时发生异常。以下部分出错:-第5部分:在上执行“UploadPart”时出错https://s3.amazonaws.com/Server3-27-SEP-2015/S3_www_1443369605.
问题内容: 由于迁移到Swift 3,我发现很难编译使用Alamofire的项目。 上载multipartFormData时发生问题: 对成员’upload(_:to:method:headers :)的含糊引用 任何帮助,不胜感激,在此先感谢! 解决: 这就是应该在Swift 3中实现上传方法的方式 问题答案: 例如,在 Swift 3中* 使用 Alamofire 4.0.0 : * (确保您
主要内容:Maven依赖关系,HttpClient分段上传请求示例在本教程中,我们将演示如何使用Apache HttpClient 4.5进行分段上传http请求。 Maven依赖关系 我们使用maven来管理依赖关系,并使用Apache HttpClient 4.5版本。 将以下依赖项添加到您的项目中。 pom.xml 文件的内容如下 - HttpClient分段上传请求示例 在这个例子中,我们将演示如何使用HttpClient 4.5来分段上传文件。 我们使
我编写了以下代码来使用多部分上传(每个部分大于5 MB)将集合字符串上传到S3,但当我从S3下载回来时,它只包含来自一个部分的字符串。 我按以下顺序调用上述代码。 创建低级多部分上传对象 循环上传零件 呼叫完成上传
根据Amazon多部分上传文档,除最后一部分外,每个部分的大小必须至少为5MB。http://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadUploadPart.html 问题是我如何通过多部分上传api将小于5MB的文件上传到AWS S3存储桶。我问这个问题的原因是,我想在上传到S3时对所有文件使用多部分上传API