一、文件异步上传
图片不随表单一起提交,而是异步上传
1、前端html、css、js
1、css代码 /*去除图片预览未选择时默认时的边框*/ img[src=""],img:not([src]){ opacity:0; display: none; } 2、表单 <div> <input id="file" type="file"/> <input type="button" value="上传" th:onclick="uploadImg();" /> //图片预览 <img id="preview_photo" src="" width="100" height="100px"> //图片地址隐藏域 <input style="display: none;" name="img" id="imgId"> </div> 3、js代码 window.uploadImg = function () { var type = "file"; //后台接收时需要的参数名称,自定义即可 var id = "file"; //即input的id,用来寻找值 var formData = new FormData(); formData.append(type, $("#"+id)[0].files[0]); //生成一对表单属性 $.ajax({ type: "POST", //因为是传输文件,所以必须是post url: '/upload', //对应的后台处理类的地址 data: formData, processData: false, contentType: false, success: function (data) { $("#preview_photo").attr("src",data.data); $("#imgId").val(data.data); layer.msg("上传成功"); console.log(data.data); } }); };
2、后端
@RestController public class CommonController { @Resource private SystemConfig systemConfig; /** * 统一文件上传 * @param file 文件 * @param request 请求 * @return result对象 * @throws IOException 异常 */ @RequestMapping("/upload") public Result upload(MultipartFile file, HttpServletRequest request) throws IOException { //单文件不为空 if (!file.isEmpty()) { //文件原始名 String originalFilename = file.getOriginalFilename(); //新的文件名 String newFileName = DateUtils.dateTimeNow()+originalFilename; /* * 保存到文件服务器、磁盘、或者阿里云对象存储(oss服务器)等方式,这里存到本地指定磁盘的位置 * 使用transferTo保存文件,也可以通过原生的输入流 headImg.getInputStream();进行保存, */ file.transferTo((new File(systemConfig.getUpload() + newFileName))); String url = systemConfig.getResource() + newFileName; //返回保存的url return Result.success(url); } return Result.error("图片不能为空"); } }
SystemConfig配置类
/** * 读取项目相关配置 */ @Component @ConfigurationProperties(prefix = "system") public class SystemConfig { //项目相关配置 private String system; //名称 private String name; //版本 private String version; //版权年份 private String copyrightYear; //获取上传路径 private String upload; //验证码类型 math 数组计算 char 字符验证 private String captchaType; private String resource; //get set方法 }
配置文件
# 项目相关配置 system.name=demo # 版本 system.version=1.0.0 # 版权年份 system.copyrightYear=2021 # 文件路径 示例( Windows配置E:/img/,Linux配置 /home/demo/resources) system.upload=E:/img/ #需要映射的静态资源路径 system.resource=/upload/** # 验证码类型 math 数组计算 char 字符验证 system.captchaType=math
3、路径映射
@Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler(systemConfig.getResource()).addResourceLocations("file:"+systemConfig.getUpload()); } }
二、表单提交上传
文件和其他数据一起通过表单上传
前端html
<!--表单上传使用post enctype必须为multipart/form-data--> <form th:action="@{/upload}" method="post" enctype="multipart/form-data"> 用户名:<input type="text" name="userName"> 头像:<input type="file" name="headImg"> <!--多文件加个 multiple--> 作品:<input type="file" name="photos" multiple> <button type="submit">提交</button> </form>
后端
/** * MultipartFile会自动封装上传来的文件 * * @param userName 普通参数 * @param headImg 单文件 * @param photos 多文件数组 * @return */ @RequestMapping("/upload") public String upload(@RequestParam("userName") String userName, @RequestPart("headImg") MultipartFile headImg, @RequestPart("photos") MultipartFile[] photos) throws IOException { //单文件不为空 if (!headImg.isEmpty()) { /**保存到文件服务器、磁盘、或者阿里云对象存储(oss服务器)等方式,这里存到本地指定磁盘的位置 */ //文件原始名 String originalFilename = headImg.getOriginalFilename(); //使用transferTo保存文件,也可以通过原生的输入流 headImg.getInputStream();进行保存, headImg.transferTo(new File("E:\\img\\" + originalFilename)); } //多文件不为空 if(photos.length > 0){ for (MultipartFile photo:photos){ if(!photo.isEmpty()){ String originalFilename = photo.getOriginalFilename(); photo.transferTo(new File("E:\\img\\" + originalFilename)); } } } return "index"; }
三、文件上传原理
Springboot当引入spring-boot-starter-web依赖后,就可以实现文件上传,关于文件上传的自动配置类是MultipartAutoConfiguration
@Configuration( proxyBeanMethods = false ) @ConditionalOnClass({Servlet.class, StandardServletMultipartResolver.class, MultipartConfigElement.class}) @ConditionalOnProperty( prefix = "spring.servlet.multipart", name = {"enabled"}, matchIfMissing = true ) @ConditionalOnWebApplication( type = Type.SERVLET ) @EnableConfigurationProperties({MultipartProperties.class}) public class MultipartAutoConfiguration { private final MultipartProperties multipartProperties; public MultipartAutoConfiguration(MultipartProperties multipartProperties) { this.multipartProperties = multipartProperties; } @Bean @ConditionalOnMissingBean({MultipartConfigElement.class, CommonsMultipartResolver.class}) public MultipartConfigElement multipartConfigElement() { return this.multipartProperties.createMultipartConfig(); } @Bean( name = {"multipartResolver"} ) @ConditionalOnMissingBean({MultipartResolver.class}) public StandardServletMultipartResolver multipartResolver() { StandardServletMultipartResolver multipartResolver = new StandardServletMultipartResolver(); multipartResolver.setResolveLazily(this.multipartProperties.isResolveLazily()); return multipartResolver; } }
能配置的都是以spring.servlet.multipart开头,进入MultipartProperties,可以查看能够配置的有哪些属性
@ConfigurationProperties( prefix = "spring.servlet.multipart", ignoreUnknownFields = false ) public class MultipartProperties { private boolean enabled = true; private String location; //单个文件最大1MB private DataSize maxFileSize = DataSize.ofMegabytes(1L); //一次请求总共的大小10MB private DataSize maxRequestSize = DataSize.ofMegabytes(10L); private DataSize fileSizeThreshold = DataSize.ofBytes(0L); private boolean resolveLazily = false; public MultipartProperties() { }
所以我们在配置文件中可以如下配置
#文件上传 spring.servlet.multipart.max-file-size=10MB spring.servlet.multipart.max-request-size=100MB
参考
@ResponseBody @RequestMapping("/upload") public ResultJson uploadFile(MultipartFile uploadFile, HttpServletRequest request) { System.out.println(30/0); SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd"); String format = sdf.format(new Date()); //存放上传文件的文件夹 File file = new File("src/main/resources/static/uploadFile/" + format); if (!file.isDirectory()) { //递归生成文件夹 file.mkdirs(); } //获取原始的名字 original:最初的,起始的 方法是得到原来的文件名在客户机的文件系统名称 String oldName = uploadFile.getOriginalFilename(); //文件大小 long size = uploadFile.getSize(); //文件类型 String type = uploadFile.getContentType(); //文件新名字 String newName = new SimpleDateFormat("yyyyMMddHHmmss") .format(new Date()) + UUID.randomUUID() .toString() .replace("-", "") +oldName; try { String s = file.getAbsolutePath() + File.separator + newName; //构建真实的文件路径, file.getAbsolutePath()输出文件夹绝对路径 -- 这里的绝对路径是相当于当前项目的路径而不是“容器”路径 File newFile = new File(file.getAbsolutePath() + File.separator + newName); //转存文件到指定路径,如果文件名重复的话,将会覆盖掉之前的文件,这里是把文件上传到 “绝对路径” uploadFile.transferTo(newFile); String filePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + "/uploadFile/" + format + newName; return new ResultJson(PerformReturnEnum.SUCCESS.getStatus(), filePath); } catch (Exception e) { e.printStackTrace(); return ResultJson.error(); } }
更多web文件上传参考:https://blog.csdn.net/qq_34491508/article/details/106946674
https://blog.csdn.net/qq_42391904/article/details/104102476