MultipartFile对象使用过之后被销毁?如何解决

294 阅读2分钟

引言

本文主要介绍我们在上传文件的时候,都是使用MultipartFile对象,但是MultipartFile在项目如果要多次使用,就会遇到一个service使用完成MultipartFile之后里面的内容就被释放了,无法再次使用。

问题描述

那么遇到上面的这种问题,我们完全可以使用业务进行解决,也就是说首先让前台调用上传文件的接口,然后在调用识别接口完成识别。但是在这儿有个特殊点就是我的两个方法的入参都是MultipartFile对象,如果是使用上述的描述解决当然也可以,但是会照成我系统资源的浪费(先上传文件生成url,识别文件需要将url转化为文件),所以这里索性一次性识别+上传文件

@PostMapping("/upload")
@ApiOperation(value = "识别文件内容并上传")
public CommonResult uploadInvoice(@RequestPart("file") MultipartFile originalFile) {
//上传文件

// 识别内容
}

那么到这里思路就非常清晰了,我们可以直接入参一个MultipartFile对象,然后使用它。但是问题就在这里,我在调用上传文件之后,第二个方法调用的时候报空异常,无法找到originalFile对象了,于是就有了本篇解决这个问题。

解决方案

这里我提供几种解决思路:

  1. 就是上面提到的重新设计服务,这种情况我这里是不太适合了,上面也讲过原因了
  2. 创建ByteArrayInputStream然后将代码转化为这种流就可以多次重复使用了,但是这里就需要更改实现类了,秉持开闭原则这里我也不去使用了,提供转化代码供大家参考
byte[] fileContent = file.getBytes();
InputStream initialStream = new ByteArrayInputStream(fileContent);

// 重新创建InputStream用于uploadInvoice
InputStream streamForInvoice = new ByteArrayInputStream(fileContent);
 invSrvice.upload(streamForInvoice);
  1. 最后一个也是我的主要解决方案,创建临时文件进行缓存,然后供后续的多次调用,最好将这个临时文件删除。
  • 首先我们将原始的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);
}