我正在尝试上传1GB以上的文件,我正在使用Spring Boot。
我已经尝试了下面的代码,但我得到了内存不足的错误。
public void uploadFile(MultipartFile file) throws IOException {
try {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setBufferRequestBody(false);
restTemplate.setRequestFactory(requestFactory);
String uploadFile= restTemplate.exchange(url, HttpMethod.POST,
new HttpEntity<>(new FileSystemResource(convert(file)), headers), String.class).getBody();
} catch (Exception e) {
throw new RuntimeException("Exception Occured", e);
}
}
private static File convert(MultipartFile file) throws IOException {
File convFile = new File(file.getOriginalFilename());
convFile.createNewFile();
FileOutputStream fos = new FileOutputStream(convFile);
fos.write(file.getBytes());
fos.close();
return convFile;
}
我面临的主要问题是,我无法将MultipartFile转换为java.io.File.
我甚至尝试过用ByteArrayResource
替换FileSystemResource
,但仍然出现OOM错误。
我甚至尝试过使用以下代码:
private static File convert(MultipartFile file) throws IOException {
CommonsMultipartFile commonsMultipartFile = (CommonsMultipartFile) multipartFile;
FileItem fileItem = commonsMultipartFile.getFileItem();
DiskFileItem diskFileItem = (DiskFileItem) fileItem;
String absPath = diskFileItem.getStoreLocation().getAbsolutePath();
File file = new File(absPath);
}
但我得到了以下例外的上述片段:
org.springframework.web.multipart.commons.commons MultipartFile无法转换为org.springframework.web.multipart.MultipartFile
有人能告诉我如何将MultipartFile转换为java.io.File吗?
还有比
FileSystemResource
更好的其他方法吗?bcoz我每次上传之前都必须在服务器中创建新文件。如果文件超过1GB,则必须在服务器端创建另一个1GB的新文件,并且必须再次手动删除该文件,我个人不喜欢这种方法。
getBytes()
试图将整个字节数组加载到内存中,这导致了OOM
需要做的是流式传输文件并将其写入。
尝试以下操作:
private static Path convert(MultipartFile file) throws IOException {
Path newFile = Paths.get(file.getOriginalFilename());
try(InputStream is = file.getInputStream();
OutputStream os = Files.newOutputStream(newFile))) {
byte[] buffer = new byte[4096];
int read = 0;
while((read = is.read(buffer)) > 0) {
os.write(buffer,0,read);
}
}
return newFile;
}
我更改了您的方法以返回Path
,而不是File
,后者是java.nio
包的一部分。该封装比java.io
更受欢迎,因为它经过了更多的优化。
如果您确实需要File
对象,可以调用newFile.toFile()
由于它返回了一个Path
对象,您可以使用java.nio.file.Files
类将文件写入后重新定位到您的首选目录
private static void relocateFile(Path original, Path newLoc) throws IOException {
if(Files.isDirectory(newLoc)) {
newLoc = newLoc.resolve(original.getFileName());
}
Files.move(original, newLoc);
}