目录
1、前端表单
form标签中必须::action="@{xxx}" ,method="post" ,enctype="multipart/form-data"属性
如果是多文件上传,则在前端页面的<input>标签中添加一个multiple属性
2、文件上传后端代码
使用@RequestPart("xxx")来接收前端传送过来的文件,会自动将前端传递过来的文件封装成MultipartFile对象
步骤:1、判断上传的文件是否为空
2、通过getOriginalFilename获取上传文件的名称
3、使用FileNmaeUtil工具类获取文件名称:UUID+文件后缀
4、获取文件要存储的文件夹
5、存储文件
upload接口:
@ApiOperation("头像上传")
@PostMapping("/uploadHeadImg")
@SystemControllerLog(description ="上传教师头像")
public CommonResult uploadteacherImg(MultipartFile file){
System.out.println("前端传入的文件:"+file);
String originalFilename = file.getOriginalFilename();
String savefileName="";
if (!file.isEmpty()) {//如果上传的头像不为空
//存储头像到tecaherHeadImg目录下
//获取文件原来的名字
//获取文件类型
String fileType = FileNameUtil.getFileType(originalFilename);
//更改文件存储的名称,避免上传的文件名重复而覆盖
savefileName = FileNameUtil.getUUIDFileName() + fileType;
//获取项目根路径
String path = System.getProperty("user.dir");
//获取文件存储路径 路径可能不存在,要用file来判断
String savePath = path+"/src/main/resources/image/teacherHeadimg/";
//头像存储路径
File realpath=new File(savePath);
//如果路径不存在,就创建路径,上传到服务器部署的时候,肯定没有这个路径存在的
if(!realpath.exists())
{
realpath.mkdirs();
}
//文件转存
try {
file.transferTo(new File(realpath.getAbsolutePath() + File.separator + savefileName));
System.out.println("存储路径:" + realpath.getAbsolutePath() + File.separator + savefileName);
return CommonResult.success("/teacherImg/" + savefileName, "头像上传成功!");
} catch (IOException e) {
e.printStackTrace();
return CommonResult.failed("上传失败!");
}
}
return CommonResult.success("/teacherImg/" + savefileName, "头像上传成功!");
}
FileNmaeUtil工具类:
public class FileNameUtil {
//根据UUID生成文件名
public static String getUUIDFileName() {
UUID uuid = UUID.randomUUID();
return uuid.toString().replace("-", "");
}
//根据给定的文件名和后缀截取文件名
public static String getFileType(String fileName){
//9527s.jpg
int index = fileName.lastIndexOf(".");
return fileName.substring(index);
}
}
注意: 1、 存储的文件名不能重复,否则上传同名文件会覆盖。这里使用的是UUID+文件后缀,保证每个上传的文件名唯一
2、springboot中获取根目录不能使用request.getServletContext().getRealPath("/") 使用这个返回的是一个临时文件夹的地址,每次重启服务器后都会不一样
3、上传文件的文件夹要判断是否存在,不存在要创建
3、文件上传配置
Springboot默认配置:
在springboot配置文件中修改默认配置:spring.servlet.multipart.xxx=xxx
4、测试
本地查看是否上传成功:
单文件:
多文件:
5、图片上传后对其进行访问
如果直接访问静态资源是访问不到的,需要进行路由映射
@Configuration
public class WebConfigurer implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
//获取项目在本机上的路径 动态获取
String ValuePath = System.getProperty("user.dir");
//图片存储的真实路径
String path=ValuePath+"\\src\\main\\resources\\image";
// 将路由/image/** 映射到真实路径
registry.addResourceHandler("/image/**").addResourceLocations("file:"+path+"/");
}
}
配置完成后就可以直接访问image目录下的静态资源
6、端是使用element异步上传文件
在用户注册时,选择图片就立即调用该接口进行文件上传。上传完成后,返回图片存储路径。
package com.rk.admin.utils;
import com.rk.admin.aop.SystemControllerLog;
import com.rk.admin.tools.CommonResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
@Api(tags = "头像上传")
@RestController
@CrossOrigin //前后端分离配置跨域访问
@RequestMapping("/uploadHeadImg")
public class uploadImgController {
@ApiOperation("教师头像上传")
@SystemControllerLog(description ="上传教师头像")
@PostMapping
public CommonResult upload(MultipartFile file){
System.out.println("前端传入的文件:"+file);
String originalFilename = file.getOriginalFilename();
String savefileName="";
if (!file.isEmpty()) {//如果上传的头像不为空
//存储头像到tecaherHeadImg目录下
//获取文件原来的名字
//获取文件类型
String fileType = FileNameUtil.getFileType(originalFilename);
//更改文件存储的名称,避免上传的文件名重复而覆盖
savefileName = FileNameUtil.getUUIDFileName() + fileType;
//获取项目根路径
String path = System.getProperty("user.dir");
//获取文件存储路径
String savePath = path + "/src/main/resources/image/teacherHeadImg/";
//文件转存
try {
file.transferTo(new File(savePath + File.separator + savefileName));
System.out.println("存储路径:" + savePath + File.separator + savefileName);
return CommonResult.success("/teacherImg/" + savefileName, "头像上传成功!");
} catch (IOException e) {
e.printStackTrace();
return CommonResult.failed("上传失败!");
}
}
return CommonResult.success("/teacherImg/" + savefileName, "头像上传成功!");
}
}
值得注意的是,这里的参数必须要用file接收,否则会报错:
7、部署到linux系统上无法访问静态资源解决方案
在windows环境中,
开发环境时:user.dir 指向的是项目的根目录;
如果将项目部署到tomcat下,user.dir指向的路径:当前用户的桌面
而在linux环境下,将项目部署到tomcat中
指向的路径为tomcat的bin目录。
所以在linux系统上直接把路径写为固定的:
对应的文件上传路径 :
将项目打包部署在服务器上时,进行图片上传,会创建1个/home/www/image/teacherImg文件夹:
由于添加了路由映射,我们可以直接通过url访问这些图片:
8、文章图片上传接口
@ApiOperation("文章上传图片")
@PostMapping("/uploadimg")
public CommonResult uploadImg(HttpServletRequest req, MultipartFile image) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
StringBuffer url = new StringBuffer();
String filePath = "/blogimg/" + sdf.format(new Date());
String imgFolderPath = req.getServletContext().getRealPath(filePath);
System.out.println("文章图片上传目录:"+imgFolderPath);
File imgFolder = new File(imgFolderPath);
if (!imgFolder.exists()) {
imgFolder.mkdirs();
}
url.append(req.getScheme())
.append("://")
.append(req.getServerName()) //拼接ip
.append(":")
.append(req.getServerPort()) //拼接端口
.append(req.getContextPath()) //获取路径
.append(filePath);
String imgName = UUID.randomUUID() + "_" + image.getOriginalFilename().replaceAll(" ", "");
try {
IOUtils.write(image.getBytes(), new FileOutputStream(new File(imgFolder, imgName)));
url.append("/").append(imgName);
System.out.println("图片url:"+url.toString());
return CommonResult.success(url.toString());
} catch (IOException e) {
e.printStackTrace();
}
return CommonResult.failed("上传失败");
}
8.1本地测试
重启服务器后无法访问,因为每次重启,tomcat都会创建不同的临时文件夹:
所以服务器每次重启后都会都会访问不到之前的静态资源,因为新的文件夹里没有之前的静态资源。
8.2、部署在服务器上测试
查看日志:
也可以直接访问:
这种方式不需要做路由映射,直接将文件上传到tomcat中,所以可以直接访问。重启后依旧不能访问。所以必须要按着之前那样,将上传文件的目录固定下来,然后做一个路由映射才不会出现这种问题。
9、文件下载
9.1、直接使用静态资源的路径,配置路由映射可以直接下载。
9.2、使用流的形式下载
//文件下载
@GetMapping("/download")
public void download(String name, HttpServletResponse response){
try {
//通过输入流,读取文件内容
FileInputStream fs=new FileInputStream(new File(uploadPath+name));
//输出流将文件写回浏览器
ServletOutputStream os = response.getOutputStream();
response.setContentType("image/jpeg");
int len=0;
byte[] bytes=new byte[1024];
while((len=fs.read(bytes))!=-1)
{
os.write(bytes,0,len);
os.flush();
}
//关闭资源
os.close();
fs.close();
} catch (Exception e) {
e.printStackTrace();
}
}
调用接口: