目录
一、文件异步上传
图片不随表单一起提交,而是异步上传
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