引言
本文主要介绍我们在上传文件的时候,都是使用MultipartFile对象,但是MultipartFile在项目如果要多次使用,就会遇到一个service使用完成MultipartFile之后里面的内容就被释放了,无法再次使用。
问题描述
那么遇到上面的这种问题,我们完全可以使用业务进行解决,也就是说首先让前台调用上传文件的接口,然后在调用识别接口完成识别。但是在这儿有个特殊点就是我的两个方法的入参都是MultipartFile对象,如果是使用上述的描述解决当然也可以,但是会照成我系统资源的浪费(先上传文件生成url,识别文件需要将url转化为文件),所以这里索性一次性识别+上传文件
@PostMapping("/upload")
@ApiOperation(value = "识别文件内容并上传")
public CommonResult uploadInvoice(@RequestPart("file") MultipartFile originalFile) {
//上传文件
// 识别内容
}
那么到这里思路就非常清晰了,我们可以直接入参一个MultipartFile对象,然后使用它。但是问题就在这里,我在调用上传文件之后,第二个方法调用的时候报空异常,无法找到originalFile对象了,于是就有了本篇解决这个问题。
解决方案
这里我提供几种解决思路:
- 就是上面提到的重新设计服务,这种情况我这里是不太适合了,上面也讲过原因了
- 创建
ByteArrayInputStream然后将代码转化为这种流就可以多次重复使用了,但是这里就需要更改实现类了,秉持开闭原则这里我也不去使用了,提供转化代码供大家参考
byte[] fileContent = file.getBytes();
InputStream initialStream = new ByteArrayInputStream(fileContent);
// 重新创建InputStream用于uploadInvoice
InputStream streamForInvoice = new ByteArrayInputStream(fileContent);
invSrvice.upload(streamForInvoice);
- 最后一个也是我的主要解决方案,创建临时文件进行缓存,然后供后续的多次调用,最好将这个临时文件删除。
- 首先我们将原始的
MultipartFile生成一份File文件 - 然后在我们需要使用的时候通过流在转化为
MultipartFile供业务使用 - 最后我们在删除这个临时文件(比较重要,如果不删除可能导致内容被极大浪费) 代码示例:
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;
//.....................
// 将原始文件内容保存到临时文件
File tempFile = File.createTempFile("upload_", "_temp");
originalFile.transferTo(tempFile);
try {
// 从临时文件创建新的MultipartFile实例
MultipartFile fileForUploadService = createMultipartFile(tempFile, originalFile);
FileResultVo resultVo = uploadService.fileUpload(fileForUploadService);
MultipartFile fileOverService = createMultipartFile(tempFile, originalFile);
Ocr ocr = ocrService.upload(fileOverService);
// 处理临时文件...
} catch (Exception e) {
throw new RuntimeException("处理文件时出错:" + e.getMessage());
} finally {
tempFile.delete(); // 删除临时文件
}
}
private MultipartFile createMultipartFile(File file, MultipartFile originalFile) throws IOException {
FileInputStream input = new FileInputStream(file);
return new MockMultipartFile("file", originalFile.getOriginalFilename(), originalFile.getContentType(), input);
}