1. 什么是MultipartFile?

MultipartFile是spring用来处理文件封装的一个接口,继承自InputStreamSource,而InputStreamSource接口中封装了getInputStream方法,所以这也是为什么MultipartFile能处理文件流的原因。

MultipartFile 作为对象的其中一个属性 传参 java multipartfile详解_multipartFile

2. MultipartFile有哪些方法

方法名称

描述

String getName()

获取的是前后端约定的传入文件的参数的名称

String getOriginalFileName()

获取的是文件的完整名称,包括文件名称+文件拓展名

String getContentType()

获取的是文件的类型,注意是文件的类型,不是文件的拓展名

boolean isEmpty()

用来判断传入的文件是否为空,如果为空则表示没有传入任何文件

long getSize()

获取文件的大小,单位是字节

byte[] getBytes()

将文件转换成一种字节数组的方式进行传输,会抛出IOException异常

InputStream getInputStream()

将文件转换成输入流的形式来传输文件,会抛出IOException异常

void transferTo(File dest)

将接收文件传输到给定目标路径

3. MultipartFile相关spring参数配置

涉及到文件上传和下载,免不了要进行服务关于文件上传的大小限制的配置,如果涉及到nginx的转发,也注意要进行相关参数的配置,否则可能导致调用接口失败,其中,spring针对MultipartFile的配置基本如下:

spring: 
  servlet:
    multipart:
      max-file-size: 100MB  # 单个数据大小限制
      max-request-size: 100MB # 单次总上传数据大小

4. HTTP封装发送MultipartFile

  1. 文件转MultipartFile
    引入maven依赖
<dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.1</version>
        </dependency>
/**
     * file转MultipartFile
     *
     * @param file 本地文件路径
     * @return
     */
    public static MultipartFile fileToMultipartFile(File file) {
        FileItem fileItem = createFileItem(file);
        MultipartFile multipartFile = new CommonsMultipartFile(fileItem);
        return multipartFile;
    }

    private static FileItem createFileItem(File file) {
        FileItemFactory factory = new DiskFileItemFactory(16, null);
        FileItem item = factory.createItem("textField", "text/plain", true, file.getName());
        int bytesRead = 0;
        byte[] buffer = new byte[8192];
        try {
            FileInputStream fis = new FileInputStream(file);
            OutputStream os = item.getOutputStream();
            while ((bytesRead = fis.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            os.close();
            fis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return item;
    }
  1. 封装HTTP请求返回DTO对象
@Data
@AllArgsConstructor
public class HttpResultDTO {

    /**
     * 返回的状态码
     */
    private int status;

    /**
     * 返回的数据信息
     */
    private String body;

    /**
     * 返回的头信息
     */
    private Map<String, String> header;
}
  1. 封装HTTP请求
/**
     * 发送multipartFile
     *
     * @param url           请求路径
     * @param file          MultipartFile流
     * @param fileParamName controller对应的接收名称
     * @param headerParams  追加的请求头信息
     * @param otherParams   其他请求参数
     * @return
     */
    public static HttpResultDTO postMultipartFile(String url, MultipartFile file, String fileParamName,
                                                  Map<String, String> headerParams,
                                                  Map<String, String> otherParams) {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        try {
            String fileName = file.getOriginalFilename();
            HttpPost httpPost = new HttpPost(url);
            //添加header
            if (headerParams != null) {
                for (Map.Entry<String, String> e : headerParams.entrySet()) {
                    httpPost.addHeader(e.getKey(), e.getValue());
                }
            }
            MultipartEntityBuilder builder = MultipartEntityBuilder.create();
            builder.setCharset(Charset.forName("utf-8"));
            //加上此行代码解决返回中文乱码问题
            builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
            //文件流处理
            builder.addBinaryBody(fileParamName, file.getInputStream(), ContentType.MULTIPART_FORM_DATA, fileName);
            if (otherParams != null) {
                for (Map.Entry<String, String> e : otherParams.entrySet()) {
                    //追加其他请求参数信息
                    builder.addTextBody(e.getKey(), e.getValue());
                }
            }
            HttpEntity entity = builder.build();
            httpPost.setEntity(entity);
            //执行提交
            HttpResponse response = httpClient.execute(httpPost);
            HttpEntity responseEntity = response.getEntity();
            StatusLine statusLine = response.getStatusLine();
            int status = statusLine.getStatusCode();
            Header[] headers = response.getAllHeaders();
            String body = EntityUtils.toString(responseEntity);
            Map<String, String> headerMap = Maps.newHashMap();
            if (ArrayUtils.isNotEmpty(headers)) {
                for (Header header : headers) {
                    headerMap.put(header.getName(), header.getValue());
                }
            }
            return new HttpResultDTO(status, body, headerMap);

        } catch (Exception e) {
            //打印日志
            LOGGER.error("postMultipartFile error,url:{},ex:{}", url, e.getMessage());
        }
        return null;
    }

5. 接收MultipartFile并处理

/**
     * 文件接收处理controller
     *
     * @param file      MultipartFile文件流
     * @param accountId 账号id
     * @return
     */
    @PostMapping("/uploadAudienceFile")
    public Response<Boolean> uploadAudienceFile(@RequestParam MultipartFile file,
                                                @RequestParam(required = false) Long accountId,
                                                @RequestParam(required = false) Long audienceId,
                                                @RequestParam(required = false) String userIdType) throws IOException {
        //入参强校验
        Preconditions.checkArgument(accountId != null, "广告账号为空");
        //文件流的封装
        String fileName = file.getOriginalFilename();
        MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder
                .create();
        multipartEntityBuilder.addBinaryBody("file", file.getInputStream(),
                ContentType.MULTIPART_FORM_DATA, fileName);
        multipartEntityBuilder.addTextBody("filename", fileName);
        //请求参数的封装
        multipartEntityBuilder.addTextBody("account_id", String.valueOf(accountId));
        multipartEntityBuilder.addTextBody("audience_id", String.valueOf(audienceId));
        multipartEntityBuilder.addTextBody("user_id_type", userIdType);
        //todo 后续的业务逻辑


        return Response.success(true);
    }

6. 设置接收和传递文件的最大值

spring:
  servlet:
    multipart:
      max-file-size: 100MB
      max-request-size: 100MB