MultipartFile 只能封装单个文件。 可以处理上传的文件。但是上传的文件可以不采用MultipartFile 的方式。可以采用其他方式处理。
表单的处理必须要用 enctype=“multipart.form-data”。并采用post提交
访问设置界面
- 在UserController中设置访问链接,
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping(path = "/setting", method = RequestMethod.GET)
public String getSettingPage(){
return "/site/setting";
}
}
- 修改对应HTML,(setting和对应index的header)
<a class="dropdown-item text-center" th:href="@{/user/setting}">账号设置</a>
上传获取头像
- 在配置application.properties文件中配置上传资源时存放的路径。
community.path.upload=D:/Project/workspace/file
考虑数据访问层DAO(暂时不需要动)
Service业务层
- 更新用户的headerUrl
/**
* 更新用户头像
*/
public int updateHeaderUrl(int userId, String url){
return userMapper.updateHeader(userId,url);
}
Controller
上传头像。上传存储的路径、服务器路径、项目路径、获取当前对象hostHoder
Logger logger = LoggerFactory.getLogger(UserController.class);
@Value("${community.path.upload}")
private String uploadPath;
@Value("${community.path.domain}")
private String domain;
@Value("${server.servlet.context-path}")
private String contextPath;
@Autowired
UserService userService ;
@Autowired
HostHolder hostHolder; //取当前的用户对象
/**
* 处理上传文件的请求
*/
@RequestMapping(path = "/upload", method = RequestMethod.POST)
public String uploadHeader (MultipartFile headerImg, Model model){
if(headerImg ==null){
model.addAttribute("error","您还未选择上传图片");
return "/site/setting";
}
//为了避免覆盖,文件名要加一个随机字符。同时要保证后缀名不变,因此需要先得到后缀名,暂存一下、
String filename = headerImg.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 {
headerImg.transferTo(dest);
} catch (IOException e) {
logger.error("上传文件失败:"+e.getMessage());
throw new RuntimeException("上传文件失败,服务器发生异常!",e);
}
//更新当前用户的路径
// (web 访问路径, http://localhost:8080/community/user/header/xxx.png)
User user = hostHolder.getUser();
String headUrl =domain + contextPath + "/user/header/"+ filename;
userService.updateHeaderUrl(user.getId(),headUrl);
return "redirect:/index";
}
上传图像的过程(MultipartFile 上传文件):
判空
判合法
上传
获取图片的后缀名, 修改图片名保证唯一。
获取当前用户对象 ,设置图片上传路径。
- 调Service上传
获取头像
/**
* 获取头像
*/
@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 (
OutputStream os = response.getOutputStream(); //获取字节流,输出流
FileInputStream fis = new FileInputStream(fileName);
){
//建立缓存区输出
byte [] buffer = new byte[1024];
int b = 0; //游标
while ((b = fis.read(buffer)) !=-1){
os.write(buffer,0,b);
}
} catch (IOException e) {
logger.error("读取图像失败"+e.getMessage());
}
}
放在try()内的留,Java编译器会自动创建finnal帮我们关闭。
FileInputStream 创建文件的输入流,用来读文件filename。进行批量输出,而不是按照字节输出来提高效率。 所以从 fis---->buffer---->os(respond)
- 获取头像过程
- 服务器路径解析
- 文件名后缀解析
- 设置respose的输出格式
- 从文件中读数据到缓冲区,再到response对象中。
处理对应HTML
<form class="mt-5" method="post" enctype="multipart/form-data" th:action="@{/user/upload}">
<div class="form-group row mt-4">
<label for="head-image" class="col-sm-2 col-form-label text-right">选择头像:</label>
<div class="col-sm-10">
<div class="custom-file">
<input type="file" th:class="|custom-file-input ${error==null?'':'is-invalid'}|"
id="head-image" name="headerImg" lang="es" required="">
<label class="custom-file-label" for="head-image" data-browse="文件">选择一张图片</label>
<div class="invalid-feedback" th:text="${error}"> 错误信息! </div>
</div>
</div>
</div>
<div class="form-group row mt-4">
<div class="col-sm-2"></div>
<div class="col-sm-10 text-center">
<button type="submit" class="btn btn-info text-white form-control">立即上传</button>
</div>
</div>
</form>
遇错:
There was an unexpected error (type=Internal Server Error, status=500).
上传文件失败,服务器发生异常!
java.lang.RuntimeException: 上传文件失败,服务器发生异常!
Caused by: java.io.IOException: java.io.FileNotFoundException: C:\Users\lily\AppData\Local\Temp\tomcat.8080.4074473235196648822\work\Tomcat\localhost\community\community.path.upload\1c0208b7cd0c47d3898b698545693ae1.jpg (系统找不到指定的路径。)
原因是因为写 忘记加${} ,
@Value("community.path.upload")
private String uploadPath;
@Value("community.path.domain")
private String domain;
@Value("server.servlet.context-path")
private String contextPath;
修改后 成功。
@Value("${community.path.upload}")
private String uploadPath;
@Value("${community.path.domain}")
private String domain;
@Value("${server.servlet.context-path}")
private String contextPath;
如果没有建立对应的文件夹,也会报找不到路径的错。需要手动创建对应目录。