MultipartFile
今天在写项目的时候遇到了上传头像的需求,想起了这个接口,就来记录一下吧,以后忘记了也能快速找到
文件上传向来都是一件繁琐有没有任何意义的事情,只要我们会上传一次,接下来的基本都是复制粘贴,springMVC为了简化上传文件的繁琐程度,提供了一个接口,专门用于处理文件上传,这个接口可以处理任何类型的文件里面有诸多的方法,满足了我们日常处理文件的需求
英文看起来比较吃力,就来中文解释下吧
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));
}
}
所继承的这个接口其实就只有一个方法,返回标准输入流
通过查看接口的实现类,也可以发现,底层就是利用普普通通的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();
}
}
评论区