spring - 使用 Spring Boot API 进行文件上传的 Tomcat 性能
问题描述
我有一个 Spring Boot API,其中一个端点允许用户上传视频。现在,我的控制器基本上将该文件作为 MultiPart 文件,然后将其存储在 tomcat 可访问的临时文件夹中。将其存储在磁盘上后,我会将视频推送到 S3 存储桶。
无论如何,现在对我来说,这似乎不是最佳的,就像我想一次上传 100 或 1000 个用户一样,首先将文件写入磁盘似乎真的没有性能。
作为一点背景,我将它存储在磁盘上,目的是如果推送到 S3 时出现问题,我可以重试
下面的代码可能会显示我比上面做得更好:
public Video addVideo(@RequestParam("title") String title,
@RequestParam("Description") String Description,
@RequestParam(value = "file", required = true) MultipartFile file) {
this.amazonS3ClientService.uploadFileToS3Bucket(file, title, description));
}
视频文件存储方法:
String fileNameWithExtenstion = awsS3FileName + "." + FilenameUtils.getExtension(multipartFile.getOriginalFilename());
//creating the file in the server (temporarily)
File file = new File(tomcatTempDir + fileNameWithExtenstion);FileOutputStream fos = new FileOutputStream(file);
fos.write(multipartFile.getBytes());
fos.close();PutObjectRequest putObjectRequest = new PutObjectRequest(this.awsS3Bucket, awsS3BucketFolder + UnigueId + "/" + fileNameWithExtenstion, file);
if (enablePublicReadAccess) {
putObjectRequest.withCannedAcl(CannedAccessControlList.PublicRead);
}
// Upload a file as a new object with ContentType and title
specified.amazonS3.putObject(putObjectRequest);
//removing the file created in the server
file.delete();
所以我的问题是....在 Tomcat 中是否有更好的方法来:
A) 通过控制器接收文件B) 推送到 S3
解决方案
没有其他方法可以使用多部分来做到这一点。multipart 的问题是从他们需要的请求中正确分割部分有时会被跳过或可重复。如果没有内存爆炸,那在内存中是不可能的。因此,Commons FileUpload 在达到某个阈值后会将它们缓存在磁盘上。多部分请求是最糟糕的方式。我强烈建议使用其中一个PUT
或POST
与 content type一起使用application/octet-stream
。您可以获取裸请求输入流并传递给 HttpClient 以流式传输到您的后端服务器。我在 5 年前就已经这样做了,它适用于千兆字节。我已经在 Apache HttpClient 邮件列表中发布了解决方案。
有一种可能性是在特定条件下如何工作:
- 所有部分都按照您要阅读的正确物理顺序
- 您对后端的写入速度足以支持从前端读取
消耗根部分,然后转到下一个物理部分,懒惰地处理请求体。JAX-WS RI (Metro) 可以很好地处理 XOP/MTOM 的多部分请求。从中吸取教训,因为你无法让它变得更好。
推荐阅读
- azure-devops - 如何以及在何处与 CI 共享 Git-Crypt 的私钥以解密加密文件?
- git - git - 更改子模块 URL 后出错 - 致命:需要单个修订
- javascript - 为什么有些 JavaScript 需要网络服务器?
- docker - 无法从分类帐中读取块号 3,因为在索引中找不到条目,正在跳过...?
- django - Django:validate_date() 缺少 1 个必需的位置参数:'value'
- c# - 如何使用最短路径返回多个节点?
- spring - 错误:在 Spring boot kotlin 新项目中找不到或加载主类
- python - Python face_recognition 数据集质量
- django - Django 3.0 + 频道 + ASGI + TokenAuthMiddleware
- bash - 使用bash将表格转换为文本文件中的逗号分隔