湖北省交通建设监理协会网站/seo软件服务
文件上传简介
文件上传涉及到前端和后端
前端部分三要素
一个表单,一个按钮类型为file
method:表单提交方式为post
表单编码格式:enctype="multipart/form-data" ,默认的编码格式不适合传输大型二进制数据
准备一个from表单如下放在resources目录下的static目录
有三个表单项,一个是姓名,一个是年龄,都是文本类型,还有一个文件类型,最后和一个提交按钮
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>上传文件</title>
</head>
<body><form action="/upload" method="post" enctype="multipart/form-data">姓名: <input type="text" name="username"><br>年龄: <input type="text" name="age"><br>头像: <input type="file" name="image"><br><input type="submit" value="提交"></form></body>
</html>
使用form表单默认格式发送数据时在请求头中有如下
查看提交的源格式如下,只有文件的文件名提交了,内容没有提交
设置表单的属性enctype="multipart/form-data"之后
后面的---------部分是一个分割符,表单有多少个提交项就有多少个分割符。
但是提交图片视频等资源后会显示乱码
后端接收
对于普通类型的表单项可以直接在方法中声明形参,对于提交的文件spingboot中提供了一个API——MultipartFile,要接收到文件必须保证表单的名称和方法名称一致。也可以不一致但是要通过一个注解进行绑定@RequestParam
新建一个Controller类如下
@Slf4j
@RestController
public class UploadController {@PostMapping("/upload")public Result upload(String username , Integer age , MultipartFile image){log.info("文件上传:{},{},{}",username,age,image);return Result.success();}
}
启动项目使用8080端口打开前端进行提交测试
前后端输出如下
可以看见提交的name和age还有文件名以及文件的存放位置,在c盘下
改个后缀就可以查看了,并且这个只是临时文件,等到该次请求响应结束后文件就消失了
因此接收到临时文件后还要及时保存起来
文件上传——本地存储
这里要将上面服务端接收到的临时文件存储起来
在MultipartFile 中已经完成了一个现成的方法transferTo可以把文件转存到某一个磁盘文件中。
该方法需要new 一个File对象,File对象需要一个存储路径和文件名。
对于文件名 用的就是传进来的文件的原本文件名,都已经被封装在了MultipartFile对象里面了
代码如下
@PostMapping("/upload")public Result upload(String username , Integer age , MultipartFile image) throws Exception {log.info("文件上传:{},{},{}",username,age,image);//获取原始文件名String originalFilename= image.getOriginalFilename();image.transferTo(new File("H:\\images\\"+originalFilename ));return Result.success();}
postman进行文件上传测试
在断点处能看见文件名了,在相应目录下也能看见传过来的图片了,现在就是永久留存下来了
代码优化:
可能出现的问题:
1.多个上传图片的文件名可能相同,后上传的会覆盖前面上传的文件
解决方案:
保证每一个图片的名称唯一,这里使用的是spring中自带的一个工具UUID,如下图演示
有了文件名还要获取文件类型,通过文件名里面最后一个点后就是文件名的方式获取
@PostMapping("/upload")public Result upload(String username , Integer age , MultipartFile image) throws Exception {log.info("文件上传:{},{},{}",username,age,image);//获取原始文件名String originalFilename= image.getOriginalFilename();//构造唯一文件名 -uuid(通用唯一识别码)44d303a6-1b8c-43d2-996c-14f898d34a14int index=originalFilename.lastIndexOf(".");String extname=originalFilename.substring(index);String newFilename= UUID.randomUUID().toString()+extname;log.info("新的文件名:{}",newFilename);image.transferTo(new File("H:\\images\\"+newFilename ));return Result.success();}
postman测试后输出如下,成功实现
2.上传的文件大小可能会超过限制
这里默认的限制大小是1mb
在springboot里面进行如下配置
然后这里传一个175Mb的视频进行测试
经过测试 得到一个结论,视频文件的大小限制是在多个文件限制那里,而不是单个文件限制
像上面这种方式比较少用,因为存在服务器后前端没有办法直接访问,并且磁盘满后无法扩容,磁盘损坏直接消失。
MultipartFile常用方法如下所示
现在资源的存储要么通过FastDFS这种分布式文件系统,要么就是MinIO这种对象存储服务搭建集群解决。