解决的问题:
本篇文章除了解决上传图片并显示的问题,还有就是在新增和修改下的图片上传如何处理。在这里新增和修改的页面是同一页面,修改的时候,将会把值带过去,但是由于类型为file的input标签是不能给其赋值的,那么若不改变原来图片,但是input标签中又没有值,这时怎么处理呢?
一 运行环境
开发工具:IDEA
后端:Springboot+JPA+thymeleaf
前端:semantic UI框架
二 代码实现
springboot中已经内嵌了上传图片的依赖包,因此不需要再添加额外依赖。
1 前端页面
<form id="blog-form" action="#" th:object="${blog}" th:action="@{/admin/blogs}" method="post" enctype="multipart/form-data" class="ui form">
<!--该部分内容省略,以下为重点-->
<div class="required field">
<div class="ui left labeled input">
<label class="ui teal basic label">首图</label>
<img src="" th:src="@{*{firstPicture}}" alt="" style="width: 500px !important;">
<!-- 不能给input type="file"文件赋值-->
<input type="file" name="picture">
<!--<input type="text" name="firstPicture" th:value="*{firstPicture}" placeholder="首图引用地址">-->
</div>
</div>
<!--该部分内容省略,以上为重点-->
<div class="ui right aligned">
<button type="button" class="ui button" onclick="window.history.go(-1)">返回</button>
<button type="button" id="save-btn" class="ui secondary button">保存</button>
<button type="button" id="publish-btn" class="ui teal button">发布</button>
</div>
</form>
注意:enctype的值为multipart/form-data
2 创建上传图片类——UploadImageUtils
从前端获取到图片之后,需要对图片进行以下处理:①更改图片文件名;②创建存放图片的文件夹;③将图片存储到文件夹中。
返回值:不带磁盘符的图片路径名。如:原图片路径为E:/picture/sdafasfhnj213.jpg,则存放在数据库中的图片路径为/picture/sdafasfhnj213.jpg。
package com.hdq.blog_3.util;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.util.UUID;
public class UploadImageUtils {
// 文件上传
public static String upload(MultipartFile file){
if(file.isEmpty()){
return "";
}
String fileName = file.getOriginalFilename();//获取文件名
String suffixName = fileName.substring(fileName.lastIndexOf("."));//获取文件后缀名
//重命名文件
fileName = UUID.randomUUID().toString().replaceAll("-","") + suffixName;
//windows下
String filePath="E:/picture/";
//centos下
//String filePath="/opt/findBugWeb/picture/";
File dest = new File(filePath+fileName);
if(!dest.getParentFile().exists()){
dest.getParentFile().mkdirs();
}
try{
file.transferTo(dest);
}catch (IOException e){
e.printStackTrace();
}
return filePath.substring(filePath.indexOf("/"))+fileName;
}
}
3 配置图片访问路径的类——SourceMapperConfig
该类可以指定图片的访问路径。当访问图片时,通过配置这个类,springboot会去指定的磁盘路径访问图片资源。
package com.hdq.blog_3.sourceMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
//配置文件访问路径
@Configuration
public class SourceMapperConfig implements WebMvcConfigurer {
private String fileSavePath = "E:/picture/";
//String fileSavePath="/opt/findBugWeb/picture/";
/**
* 配置资源映射
* 意思是:如果访问的资源路径是以“/picture/”开头的,
* 就给我映射到本机的“E:/picture/”这个文件夹内,去找你要的资源
* 注意:E:/picture/ 后面的 “/”一定要带上
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/picture/**").addResourceLocations("file:"+fileSavePath);
}
}
4 创建Controller类——BlogController
用MultipartFile类获取前端传过来的图片文件。在新增与修改情况下,如何上传图片,并显示呢?步骤如下:
①新增时,直接保存图片,图片可以为空。
②修改时,若没有上传图片,则将数据库中原来的图片取出来赋值给当前图片,再保存到数据库中,否则,直接保存上传的图片。
package com.hdq.blog_3.web.admin;
import com.hdq.blog_3.po.Blog;
import com.hdq.blog_3.po.User;
import com.hdq.blog_3.service.BlogService;
import com.hdq.blog_3.service.TagService;
import com.hdq.blog_3.service.TypeService;
import com.hdq.blog_3.util.UploadImageUtils;
import com.hdq.blog_3.vo.BlogQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.web.PageableDefault;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import javax.servlet.http.HttpSession;
@Controller
@RequestMapping("/admin")
public class BlogController {
private static final String INPUT="admin/blogs-input";
private static final String LIST="admin/blogs";
private static final String REDIRECT_LIST="redirect:/admin/blogs";
@Autowired
private BlogService blogService;
@Autowired
private TypeService typeService;
@Autowired
private TagService tagService;
private void setTypeAndTag(Model model){
model.addAttribute("types",typeService.listType());
model.addAttribute("tags",tagService.listTag());
}
//新增 or 修改
@PostMapping("/blogs")
public String post(@RequestParam("picture") MultipartFile picture, Blog blog, RedirectAttributes attributes, HttpSession session){
blog.setUser((User) session.getAttribute("user"));
blog.setType(typeService.getType(blog.getType().getId()));
blog.setTags(tagService.listTag(blog.getTagIds()));
//1.修改:picture为空,则不改变FirstPicture,否则改变FirstPicture。
//2.新增:直接添加图片文件
Blog b;
if(blog.getId() == null){
blog.setFirstPicture(UploadImageUtils.upload(picture));//重点
b=blogService.saveBlog(blog);
}else{
// isEmpty()与null的区别:前者表示内容是否为空,后者表示对象是否实例化,在这里前端发送请求到后端时,就实例化了picture对象
if(picture.isEmpty()){
blog.setFirstPicture(blogService.getBlog(blog.getId()).getFirstPicture());//重点
}else {
blog.setFirstPicture(UploadImageUtils.upload(picture));//重点
}
b=blogService.updateBlog(blog.getId(),blog);
}
if(b == null){
attributes.addFlashAttribute("message","操作失败!");
}else{
attributes.addFlashAttribute("message","操作成功!");
}
return REDIRECT_LIST;
}
}
注意:以上部分不重要的代码已删掉,只留下重要部分。
5 运行逻辑:
①图片上传时,前端将图片传送给BlogController类,BlogController类中获取到图片,然后调用UploadImageUtils类,修改图片名并保存图片到磁盘,再返回图片路径给BlogController类,BlogController类将图片路径保存到数据库。
②图片显示时,前端获取到图片路径,根据SourceMapperConfig类配置的图片访问路径去访问图片。
三 运行结果展示
1 初始页面
2 新增成功页面
a.添加图片
b.新增成功
3 修改成功页面