java - 文件上传 S3 的困惑
问题描述
我将文件保存在我的 S3 存储桶上,但我注意到为此我使用了FileOutPutStream
这样的方法:
private UploadedFile file; // This is from PrimeFaces, the file that the client wishes to upload
File uploadedFile = new File(file.getFileName()); // Leaving the file like this creates the file on my IDE folder AFTER executing the next two lines, thats why I though the next lines were an error.
FileOutputStream fileOutput = new FileOutputStream(uploadedFile);
fileOutput.write(file.getContents());
所以这行代码负责在我的设备上写入文件,我首先认为这是一个错误或者没有必要,因为我对文件上传到亚马逊不太了解,所以我删除了这两行,因为我注意到我的上传方法只需要文件和文件名,如下所示:
businessDelegatorView.uploadPublicRead("mybucketname", fileName, fileToUpload);
所以我虽然这不是必需的,那只是复制文件:
FileOutputStream fileOutput = new FileOutputStream(uploadedFile);
fileOutput.write(file.getContents());
但是我注意到,如果我删除它们,上传将不起作用,因为它会抛出一个FileNotFoundException
,所以我开始搜索并从 BalusC 找到这篇文章,我明白了我必须定义一个路径,我的客户的文件将被保存为稍后像在这种情况下一样上传到亚马逊 s3 存储桶,但我想知道,例如,在生成 .WAR 时这样做是否会起作用:
File uplodadFile = new File("C:/xampp/apache/conf", file.getFileName());
FileOutputStream fileOutput = new FileOutputStream(uploadFile);
fileOutput.write(file.getContents());
我将文件保存在那里作为测试,但我不知道或不确定是否FileOutPutStream
是正确的选择,我不知道另一种方式。
这也是执行上述代码后上传方法的样子,没有FileOutPutStream
它不会工作导致文件不在我的设备中
AmazonS3 amazonS3 = buildAmazonS3();
try {
amazonS3.putObject(new PutObjectRequest(bucketName, key, file).withCannedAcl(CannedAccessControlList.PublicRead));
只是希望有人为我澄清一些事情,比如在这里放置的最佳路径是什么?
File uplodadFile = new File("C:/xampp/apache/conf", file.getFileName());
或者我只需要记住.WAR将部署在哪台机器上真的没关系?谢谢
解决方案
只是希望有人为我澄清一些事情,比如在这里放置的最佳路径是什么?
当您想将文件上传到系统中时,请尽可能将其保存为字节流,因为您会在条目中接收字节并且您希望在最后存储这些相同的字节。转换bytes->file->bytes
耗时、消耗资源且容易出错(编码转换和存储在文件系统上的文件可能确实是错误的来源)。
所以我虽然这不是必需的,那只是复制文件:
FileOutputStream fileOutput = new FileOutputStream(uploadedFile); fileOutput.write(file.getContents());
您是对的,因为该文件已由客户端 HTTP 请求上传。
做两次看起来很无奈。
但是你没有File
一个UploadedFile
(primefaces)。
S3 API的PutObjectRequest()
构造函数有几个重载。
实际上你使用它:
public PutObjectRequest(String bucketName,
String key,
File file)
最后一个参数是 a File
。你看到不匹配了吗?在您第一个让您烦恼的代码中,File
您UploadedFile
通过将UploadedFile
File
File
.
但实际上您不需要 File 因为PutObjectRequest()
构造函数有另一个更适合您使用的重载:
public PutObjectRequest(String bucketName,
String key,
InputStream input,
ObjectMetadata metadata)
构造一个新的 PutObjectRequest 对象以将数据流上传到指定的存储桶和键。构建请求后,用户还可以选择指定对象元数据或标准 ACL。
请注意,为了不损害性能,提供内容长度很重要:
数据流的内容长度必须在对象元数据参数中指定;Amazon S3 要求在上传数据之前将其传入。未能指定内容长度将导致输入流的全部内容在内存中本地缓冲,以便可以计算内容长度,这可能会导致负面的性能问题。
所以你可以这样做:
UploadedFile file = ...; // uploaded by client
ObjectMetadata metaData = new ObjectMetadata();
metaData.setContentLength(file.getSize());
amazonS3.putObject(new PutObjectRequest(bucketName, key, file.getInputStream(), metaData)
.withCannedAcl(CannedAccessControlList.PublicRead));
推荐阅读
- git - 在 git hub 中克隆大项目
- javascript - 如何使用 Flow 要求特定对象
- android - 如何在 CoordinatorLayout 中的 AppBarLayout 下面制作 ViewStub
- ruby-on-rails - 如果用户编辑该字段,建议按钮应显示消息。如何?
- laravel - 如何在 Laravel 中使用 eloquent 从子表中获取价值?
- clojure - 增加一个原子的值
- r - Rcpp:NumericVector 输入和输出改变原始输入数据,但 IntegerVector 不会
- python - Python - Pandas DF - 基于 2 个或更多列创建具有唯一值的 DataFrame
- c - 用于评估除 main 以外的函数中的字符串时,sizeof 结果的差异
- reactjs - Typescript + Reactjs - 导入的 svg 不呈现