MultipartFile

今天在写项目的时候遇到了上传头像的需求,想起了这个接口,就来记录一下吧,以后忘记了也能快速找到

文件上传向来都是一件繁琐有没有任何意义的事情,只要我们会上传一次,接下来的基本都是复制粘贴,springMVC为了简化上传文件的繁琐程度,提供了一个接口,专门用于处理文件上传,这个接口可以处理任何类型的文件里面有诸多的方法,满足了我们日常处理文件的需求

image-20220805151142388

英文看起来比较吃力,就来中文解释下吧

package org.springframework.web.multipart;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import org.springframework.core.io.InputStreamSource;
import org.springframework.core.io.Resource;
import org.springframework.lang.Nullable;
import org.springframework.util.FileCopyUtils;

public interface MultipartFile extends InputStreamSource {
//getName() 返回参数的名称
    String getName();
//获取源文件的昵称
    @Nullable
    String getOriginalFilename();
//getContentType() 返回文件的内容类型
    @Nullable
    String getContentType();
//isEmpty() 判断是否为空,或者上传的文件是否有内容
    boolean isEmpty();
//getSize() 返回文件大小 以字节为单位
    long getSize();
//getBytes() 将文件内容转化成一个byte[] 返回
    byte[] getBytes() throws IOException;
//getInputStream() 返回InputStream读取文件的内容
    InputStream getInputStream() throws IOException;

    default Resource getResource() {
        return new MultipartFileResource(this);
    }
//transferTo(File dest) 用来把 MultipartFile 转换换成 File
    void transferTo(File var1) throws IOException, IllegalStateException;

    default void transferTo(Path dest) throws IOException, IllegalStateException {
        FileCopyUtils.copy(this.getInputStream(), Files.newOutputStream(dest));
    }
}

image-20220805151435625

所继承的这个接口其实就只有一个方法,返回标准输入流

通过查看接口的实现类,也可以发现,底层就是利用普普通通的io流进行实现的

当然我们在上传的时候总会有一些的限制条件,大家可以在后端代码里面进行逻辑判断,但是这里并不需要这么做,这样反而会增加服务器的压力,我们直接可以在前端页面就进行判断使用到技术是element-UI,经常配合Vue框架进行一些按钮的开发

几组判断代码

今天写代码的时候并没有采用上述组件,写的是下面的逻辑进行判断

/**
     * 文件的最大大小
     */
    public static final int AVATAR_MAX_SIZE = 10*1024*1024;
    /**
     * 允许的文件类型
     */
    public static final List<String> AVATAR_TYPES = new ArrayList<>();

    static {
        AVATAR_TYPES.add("image/jpeg");
        AVATAR_TYPES.add("image/png");
        AVATAR_TYPES.add("image/gif");
        AVATAR_TYPES.add("image/bmp");
    }
    /**
     * multipart接收数据
     * @param session session
     * @param file 文件信息
     * @return 文件路径
     */
    @PostMapping("change_avatar")
    public JsonResult<String> changeAvatar(HttpSession session, @RequestParam("file")MultipartFile file){
        if (file.isEmpty()){
            throw new FileEmptyException("文件为空");
        }
        if (file.getSize()>AVATAR_MAX_SIZE){
            throw new FileSizeException("文件太大");
        }
        if (!AVATAR_TYPES.contains(file.getContentType())){
            throw new FileTypeException("文件类型错误");
        }
//        上传的文件
        String parent = session.getServletContext().getRealPath("upload");
        File dir = new File(parent);
        if (!dir.exists()){
            dir.mkdirs();
        }
//        使用UUID生成一个新的字符串,作为文件名
        String originalFilename = file.getOriginalFilename();
        assert originalFilename != null;
        String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
        String uuidName = UUID.randomUUID().toString().toUpperCase()+suffix;
        File dest = new File(dir ,uuidName);
//        将参数写入到文件中
        try {
            file.transferTo(dest);
        } catch (IOException e) {
            throw new FileUploadIoException("文件读写错误");
        } catch (FileStateException e){
            throw new FileUploadIoException("文件状态异常");
        }
        userService.changeAvatar(getUidFromSession(session),"/upload"+uuidName,getUserNameFromSession(session));
        return new JsonResult<>(OK,"/upload/"+uuidName);
    }

但是在上传的过程中依然存在一个问题,springboot默认值允许1mb以内的文件上传,这显然不满足我们的需求,这样我们就需要更改相关的配置,在springboot中,因为springboot默认给我们配置了springMVC,这样我们就可以直接使用配置文件的方式进行修改

spring:
  servlet:
    multipart:
      enabled: true #是否启用http上传处理
      max-request-size: 10MB #最大请求文件的大小
      max-file-size: 10MB #设置单个文件最大长度
      file-size-threshold: 10MB #当文件达到多少时进行磁盘写入

当然还可以给springboot中注入一个bean这样就默认使用我们注入的了

@Configuration
public class UploadConfig {
 
    @Bean
    public MultipartConfigElement multipartConfigElement() {
        MultipartConfigFactory factory = new MultipartConfigFactory();
        //单个文件最大
        factory.setMaxFileSize("20480KB"); //KB,MB
        /// 设置总上传数据总大小
        factory.setMaxRequestSize("1024000KB");
        return factory.createMultipartConfig();
    }
}