我在Java读取拼花文件时构建了一个XML字符串。该xml字符串需要上传到S3存储桶。
拼花文件最多可以有200万条记录。
将XML文件上载到S3的一种方法是使用AWS的多部分上载API,方法如下:
构建XML字符串后,将该字符串转换为inputstream,并在UploadPart Request对象中使用它来调用s3Client.uploadPart()方法。
提交人:
代码看起来像这样:
long partSize = 5242880L;
AmazonS3 s3Client = (AmazonS3)((AmazonS3ClientBuilder)AmazonS3ClientBuilder.standard().withRegion(clientRegion)).build();
List<PartETag> partETags = new ArrayList();
long filePosition = 0L;
for(int i = 1; filePosition < contentLength; ++i) {
partSize = Math.min(partSize, contentLength - filePosition);
DLFUtil.logInfo(" Part Size - " + partSize);
UploadPartRequest uploadRequest = (new UploadPartRequest()).withBucketName(objectDetails.getBucketName()).withKey(objectDetails.getS3Key()).withUploadId(objectDetails.getUploadId()).withPartNumber(i).withInputStream(body).withPartSize(partSize);
UploadPartResult uploadResult = s3Client.uploadPart(uploadRequest);
DLFUtil.logInfo("Uploaded Part " + i);
partETags.add(uploadResult.getPartETag());
filePosition += partSize;
DLFUtil.logInfo("filePosition " + filePosition);
}
CompleteMultipartUploadRequest compRequest = new CompleteMultipartUploadRequest(objectDetails.getBucketName(), objectDetails.getS3Key(), objectDetails.getUploadId(), partETags);
s3Client.completeMultipartUpload(compRequest);
面临的挑战是,由于parquet文件可能有200万条记录,所以当构建xml字符串时,它将是内存中的一个巨大的字符串(字符串大小可能以GBs为单位)。为了避免在内存中有一个巨大的字符串,我想到了分块构建字符串-
但是,由于这样做,我遇到了错误:“您建议的上传小于允许的最小大小”
我收到此错误的原因是,当我对字符串的一部分进行分段上传时,最后一部分将小于5 MB。对于另一个块的第二次分段上传,最后一部分将再次小于5 MB。当 AWS 尝试使用完整的多部分Upload() 组装所有部件时,它预计只有一个部分小于 5 MB,因为在典型情况下,输入流将具有整个字符串或文件,只有最后一个部分小于 5 MB。
我正在尝试找出一种方法来上传xml字符串,而不必一次将整个字符串保存在内存中。如果有什么建议,请告诉我。
我与AWS支持人员聊天,他们告诉我,多部分上传API的设计方式是,它只能接受小于5MB的最后一部分。因此,我们需要上传部件以满足这些要求。
为了解决这个问题,我们所做的是——只要剩余的部分大小小于5MB,我们就将输入流转换回字符串并返回字符串。构建字符串的函数将接收该字符串,并继续从那里构建字符串。
例如,我们假设整个字符串将在 701 MB 左右。另外,假设我们有一个函数 buildString(), 它生成需要上传的字符串。该函数从头开始构建字符串,当字符串超过 100 MB 时,我们会对该字符串执行分段上传(如果对象将超过 100 MB,AWS 建议以分段方式上传对象)。假设构建的字符串为 101 MB,我们为该字符串执行分段上传。AWS 的分段上传 API 预计分段对象应以 5 MB 的分段上传。因此,对于 101 MB 的字符串,将上传 5 MB 的 20 个部分,对于剩余的 1 MB 部分 - 我们将它转换回字符串并将其发送回 buildString() 函数,而不是上传它。生成字符串() 将采用该字符串并继续从那里生成字符串。当字符串长度再次超过 100 MB 时,将重复相同的步骤。这样,上传的每个部分将正好为5 MB。这个难题唯一剩下的部分是,当buildString()完成字符串的构建并上传剩余的字符串时,我们不需要返回小于5 MB的字符串。相反,这应该被上传,因为这确实是701 MB字符串的最后一部分,小于5 MB。
下表给出了一个更好的想法:表中显示了每次多部分上传的字符串长度
使用此解决方案,上传多部分的方法如下所示:
public String uploadMultipart(boolean isLastPart, InputStream body, long contentLength) throws IOException {
long partSize = 5242880L;
long filePosition = 0L;
String remainderString = null;
int i;
for (i = partNumber; filePosition < contentLength; ++i) {
if ((contentLength - filePosition) < partSize && !isLastPart) {
/**
* Do not publish the part which is less than 5 MB. Instead, convert it to string and return it back.
* The reason for that is - AWS only wants one last part to be less than 5 MB.
* However, with our custom-built solution to upload the parts while building the string, we would end up with multiple parts less than 5 MB.
* To avoid that, we will not publish the part which is less than 5 MB. We will return the string and continue building the string from there.
* Only if isLastPart is true (which indicates that we have completed building the string), we will not return the remaining string and rather upload it as
* that will indeed be the last part less than 5 MB as expected by AWS.
*/
remainderString = getStringFromInputStream(body);
break;
} else {
partSize = Math.min(partSize, (contentLength - filePosition));
UploadPartRequest uploadRequest = (new UploadPartRequest()).withBucketName(getBucketName()).withKey(getS3Key()).
withUploadId(getUploadId()).withPartNumber(i).withInputStream(body).withPartSize(partSize);
UploadPartResult uploadResult = s3Client.uploadPart(uploadRequest);
partETags.add(uploadResult.getPartETag());
filePosition += partSize;
}
}
partNumber = i;
return remainderString;
}
请注意,在这种情况下,对于每个多部分上传,UploadPart Request对象中设置的存储桶名称、S3键和上传ID应该是相同的。只有这样,AWS才会知道这些部分与同一个对象相关联,并且最终会将它们组装在一起,以便在最后调用AWS的完成多部分上传()函数时拥有我们的单个701 MB对象。
当我想上传图片到我的亚马逊s3存储桶时,我遇到了一些问题 我正试着上传一张238 KB的jpg图片。我在代码中放了一个try/catch来检查错误是什么。我总是得到这个错误: 您建议的上传小于允许的最小大小 我也用1MB和2MB的图片试过,同样的错误...。 这是我的代码: (我已经更改了桶、键和图像链接。) 以前有人有过这个吗?在互联网上搜索对我没有太大帮助。 还搜索更改最小上传大小也没有提供太
您可以使用基于浏览器的上传(不是多部分上传)中的内容长度范围字段来限制文件大小:http://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-HTTPPOSTConstructPolicy.html 你怎么能在多部分上传中限制它?我正在使用EvaporateJS。
有没有办法,如何上传比5MB更小的文件?多部分上传要求块的大小大于5MB(不包括最后一个)。但是我正在处理32KB的块。 有没有一种方法可以上传较小的块,或者让我保存我的块,直到它们达到5MB大小,然后使用多部分上传? 感谢解答!
我正在尝试将图像文件从临时php文件存储路径上传到S3。文件大小约为100 kb,最大为500 kb。 当上传发生时,我得到这个错误: 我不认为我需要在这里进行分段上传,因为文件不是太大。此外,上传从我的本地系统到 S3,但是当我在 AWS 上部署 PHP 实例时,上传会给我一个错误。任何帮助将不胜感激。 谢谢你
根据Amazon多部分上传文档,除最后一部分外,每个部分的大小必须至少为5MB。http://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadUploadPart.html 问题是我如何通过多部分上传api将小于5MB的文件上传到AWS S3存储桶。我问这个问题的原因是,我想在上传到S3时对所有文件使用多部分上传API
问题内容: 我有一个无法访问的PC上托管的网站。我有一个上传表单,允许人们上传最大30MB的mp3文件。我的服务器端脚本是用PHP完成的。 每次尝试上传文件时,都会收到一条错误消息,声称文件超出了允许的最大大小,因此我需要增加大小。我在网络上的研究建议更改我无权访问的文件,这样将无法正常工作。其他人建议我将自定义文件添加到我的根目录中,该文件无效。还有其他建议吗? 问题答案: 您需要设置的值,并在