路径问题
- 因为开发时和部署时的系统不同,所以文件路径应该是可装配的,最好写在配置文件中,通过**@Value**注解来动态获取。
//配置文件
community.path.domain=http://localhost:8080
community.path.upload=d:/work/data/upload
//控制层代码 用来获取配置文件中的路径
@Value("${community.path.upload}")
private String uploadPath;
@Value("${community.path.domain}")
private String domain;
@Value("${server.servlet.context-path}")
private String contextPath;
上传业务逻辑
-
通过MultipartFile来接收文件,如果是多个文件则以数组的形式接收
@PostMapping(path = "/upload") public String uploadHeader(MultipartFile headerImage, Model model)
-
判断文件是否为空,不为空才执行该方法
-
通过参数获得该文件的名字
String fileName = headerImage.getOriginalFilename();
- 通过文件名字来截取文件的后缀
String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);
- 因为不同用户的文件名可能相同,所以要再生成随机的文件名来防止文件覆盖
fileName = CommunityUtil.generateUUID()+suffix; //注:随便一个生成uuid的工具类即可
- 确定文件存放的路径
File dest = new File(uploadPath+"/"+fileName);
- 将文件上传到目标路径
try {//自带的上传文件的接口
headerImage.transferTo(dest);
} catch (IOException e) {
throw new RuntimeException("上传文件失败",e);
}
- 更新数据库中相关的数据(本例中是用户的头像路径)
User user = hostHolder.getUser();
String headerUrl = domain + contextPath + "/user/header/"+ fileName;
userService.updateHeader(user.getId(),headerUrl);
访问/获取业务逻辑
- 本方法的路径不能乱写,要与上面第8个配置的路径相同
@RequestMapping(path = "/header/{fileName}", method = RequestMethod.GET)
public void getHeader(@PathVariable("fileName") String fileName, HttpServletResponse response)
- 找到服务器存放路径,获得文件后缀
fileName = uploadPath + "/" + fileName;
String suffix = fileName.substring(fileName.lastIndexOf("."));
- 响应图片,修改response返回格式
//该内容类型的意思是访问图片
response.setContentType("image/" + suffix);
- response读取文件
try (
FileInputStream fis = new FileInputStream(fileName);
OutputStream os = response.getOutputStream();
) {
byte[] buffer = new byte[1024];
int b = 0;
while ((b = fis.read(buffer)) != -1) {
os.write(buffer, 0, b);
}
} catch (IOException e) {
log.error("读取头像失败: " + e.getMessage());
}
- 注:上面的第一个圆括号是java7的特性,可以自动关闭流
上传完整代码
@PostMapping(path = "/upload")
public String uploadHeader(MultipartFile headerImage, Model model){
if(headerImage == null) {
model.addAttribute("error","您还没有选择图片");
return "/site/setting";
}
String fileName = headerImage.getOriginalFilename();
String suffix = fileName.substring(fileName.lastIndexOf("."));
if(StringUtils.isBlank(suffix)){
model.addAttribute("error","文件的格式不正确");
return "/site/setting";
}
fileName = CommunityUtil.generateUUID()+suffix;
File dest = new File(uploadPath+"/"+fileName);
try {
headerImage.transferTo(dest);
} catch (IOException e) {
log.error("上传文件失败");
throw new RuntimeException("上传文件失败",e);
}
//更新当前用户头像的路径
User user = hostHolder.getUser();
String headerUrl = domain + contextPath + "/user/header/"+ fileName;
userService.updateHeader(user.getId(),headerUrl);
return "redirect:/index";
}
访问完整代码
@RequestMapping(path = "/header/{fileName}", method = RequestMethod.GET)
public void getHeader(@PathVariable("fileName") String fileName, HttpServletResponse response) {
// 服务器存放路径
fileName = uploadPath + "/" + fileName;
// 文件后缀
String suffix = fileName.substring(fileName.lastIndexOf("."));
// 响应图片
response.setContentType("image/" + suffix);
try (
FileInputStream fis = new FileInputStream(fileName);
OutputStream os = response.getOutputStream();
) {
byte[] buffer = new byte[1024];
int b = 0;
while ((b = fis.read(buffer)) != -1) {
os.write(buffer, 0, b);
}
} catch (IOException e) {
log.error("读取头像失败: " + e.getMessage());
}
}
补充
- 在读取文件返回那块,有已经写好的方法可以直接调用,在hutool依赖中
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.3</version>
</dependency>
- 调用的代码
//注:该内容类型的意思是下载而非访问
response.setContentType("application/octet-stream");
byte[] bytes=FileUtil.readBytes(basePath+fileName);
os=response.getOutputStream();
os.write(bytes);
os.flush();
os.close();