2.4 文件上传实现
步骤一:设计数据表
步骤二:配置表信息,并生成代码
generatorConfig.xml :
<table schema="" tableName="img_upload" domainObjectName="UploadImg" enableCountByExample="false" enableDeleteByExample="false" enableSelectByExample="false" enableUpdateByExample="false"> </table>
步骤三:创建业务逻辑层并实现接口...
步骤四:配置文件路径信息
resource.properties:
#本地路径 dir=D:/upload/ #服务器路径 server=/upload/
编写配置文件读取工具类
package com.ycxw.utils; import java.io.IOException; import java.io.InputStream; import java.util.Properties; /** * 配置文件读取工具类 * @author 云村小威 * @site blog.csdn.net/Justw320 * @create 2023-09-10 16:57 */ public class PropertiesUtil { public static String getValue(String key) throws IOException { Properties p = new Properties(); InputStream in = PropertiesUtil.class.getResourceAsStream("/resource.properties"); p.load(in); return p.getProperty(key); } }
步骤五:配置项目与映射地址
步骤六:编写控制器
package com.ycxw.web; import com.ycxw.biz.UploadImgBiz; import com.ycxw.model.UploadImg; import com.ycxw.utils.PageBean; import com.ycxw.utils.PropertiesUtil; import org.apache.commons.io.FileUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletRequest; import java.io.File; import java.io.IOException; import java.util.List; /** * @author 云村小威 * @site blog.csdn.net/Justw320 * @create 2023-09-10 16:50 */ @Controller @RequestMapping("/file") public class UploadImgController { @Autowired private UploadImgBiz uploadImgBiz; /*新增方法*/ @RequestMapping("/add") public String save(UploadImg uploadImg, HttpServletRequest request) { uploadImgBiz.insertSelective(uploadImg); return "redirect:list"; } /*删除方法*/ @RequestMapping("/del/{id}") public String del(@PathVariable("id") Integer id) { uploadImgBiz.deleteByPrimaryKey(id); return "redirect:/file/list"; } /*修改方法*/ @RequestMapping("/edit") public String edit(UploadImg uploadImg, HttpServletRequest request) { uploadImgBiz.updateByPrimaryKeySelective(uploadImg); return "redirect:list"; } /*查询方法*/ @RequestMapping("/list") public String list(UploadImg uploadImg, HttpServletRequest request) { PageBean pageBean = new PageBean(); pageBean.setRequest(request); List<UploadImg> uploadImgs = uploadImgBiz.listPager(uploadImg, pageBean); // ModelAndView modelAndView = new ModelAndView(); // modelAndView.addObject("UploadImgs", UploadImgs); // modelAndView.addObject("pageBean", pageBean); // modelAndView.setViewName("UploadImg/list"); request.setAttribute("uploadImgs", uploadImgs); request.setAttribute("pageBean", pageBean); return "file/list"; } /*数据回显*/ @RequestMapping("/preSave") public String preSave(UploadImg uploadImg, HttpServletRequest request) { if (uploadImg != null && uploadImg.getId() != null && uploadImg.getId() != 0) { UploadImg img = uploadImgBiz.selectByPrimaryKey(uploadImg.getId()); request.setAttribute("img", img); } return "file/edit"; } /*图片上传*/ @RequestMapping("upload") public String upload(UploadImg img,MultipartFile imgFile) throws IOException { //读取配置文夹本地路径和服务器路径 String dir = PropertiesUtil.getValue("dir"); String server = PropertiesUtil.getValue("server"); //利用MultipartFile类接受前端传递到后台的文件 System.out.println("文件名:"+imgFile.getOriginalFilename()); System.out.println("文件类型:"+imgFile.getContentType()); //将文件转成流写入到服务器 FileUtils.copyInputStreamToFile(imgFile.getInputStream(),new File(dir+imgFile.getOriginalFilename())); //通过对象将图片保存到数据库 img.setImg(server+imgFile.getOriginalFilename()); uploadImgBiz.updateByPrimaryKeySelective(img); return "redirect:list"; } }
步骤七:编写前端jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="w" uri="http://jsp.veryedu.cn" %> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.css" rel="stylesheet"> <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.5.0/js/bootstrap.js"></script> <base href="${pageContext.request.contextPath }"> <title>博客列表</title> <style type="text/css"> .page-item input { padding: 0; width: 40px; height: 100%; text-align: center; margin: 0 6px; } .page-item input, .page-item b { line-height: 38px; float: left; font-weight: 400; } .page-item.go-input { margin: 0 10px; } </style> </head> <body> <form class="form-inline" action="/file/list" method="post"> <div class="form-group mb-2"> <input type="text" class="form-control-plaintext" name="name" placeholder="请输入用户名称"> </div> <button type="submit" class="btn btn-primary mb-2">查询</button> <a class="btn btn-primary mb-2" href="/file/preSave">新增</a> </form> <table class="table table-striped"> <thead> <tr> <th scope="col">ID</th> <th scope="col">用户</th> <th scope="col">图片</th> </tr> </thead> <tbody> <c:forEach var="i" items="${uploadImgs }"> <tr> <td>${i.id }</td> <td>${i.name }</td> <td> <img src="${i.img }" style="width: 200px;height: 100px;"> </td> <td> <a href="/file/preSave?id=${i.id}">修改</a> <a href="/file/del/${i.id}">删除</a> <a href="/page/file/upload?id=${i.id}">图片上传</a> <a href="/file/download?id=${i.id}">图片下载</a> </td> </tr> </c:forEach> </tbody> </table> <!-- 这一行代码就相当于前面分页需求前端的几十行了 --> <w:page pageBean="${pageBean }"></w:page> </body> </html>
步骤8:运行测试
2.5 文件下载实现
根据传入的文件id查询对应的文件信息,然后根据文件路径读取文件内容,并将文件内容和设置好的HTTP头信息封装成一个ResponseEntity对象,最后返回给客户端进行文件下载。
@RequestMapping("/download") public ResponseEntity<byte[]> download(UploadImg uploadImg, HttpServletRequest req){ try { //先根据文件id查询对应图片信息 UploadImg img = this.uploadImgBiz.selectByPrimaryKey(uploadImg.getId()); String diskPath = PropertiesUtil.getValue("dir"); String reqPath = PropertiesUtil.getValue("server"); //上面获取的数据库地址,需要转换才能下载成本地路径 String realPath = img.getImg().replace(reqPath,diskPath); String fileName = realPath.substring(realPath.lastIndexOf("/")+1); //下载关键代码 File file=new File(realPath); HttpHeaders headers = new HttpHeaders();//http头信息 String downloadFileName = new String(fileName.getBytes("UTF-8"),"iso-8859-1");//设置编码 headers.setContentDispositionFormData("attachment", downloadFileName); headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); //MediaType:互联网媒介类型 contentType:具体请求中的媒体类型信息 return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file),headers, HttpStatus.OK); }catch (Exception e){ e.printStackTrace(); } return null; }
示例:
2.6 多文件上传、下载
1. 编写方法:
@RequestMapping("/download") public ResponseEntity<byte[]> download(UploadImg uploadImg, HttpServletRequest req) { try { //先根据文件id查询对应图片信息 UploadImg img = this.uploadImgBiz.selectByPrimaryKey(uploadImg.getId()); String diskPath = PropertiesUtil.getValue("dir"); String reqPath = PropertiesUtil.getValue("server"); //上面获取的数据库地址,需要转换才能下载成本地路径 String realPath = img.getImg().replace(reqPath, diskPath); String fileName = realPath.substring(realPath.lastIndexOf("/") + 1); //下载关键代码 File file = new File(realPath); HttpHeaders headers = new HttpHeaders();//http头信息 String downloadFileName = new String(fileName.getBytes("UTF-8"), "iso-8859-1");//设置编码 headers.setContentDispositionFormData("attachment", downloadFileName); headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); //MediaType:互联网媒介类型 contentType:具体请求中的媒体类型信息 return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file), headers, HttpStatus.OK); } catch (Exception e) { e.printStackTrace(); } return null; }
2. 编写前端页面做对比:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <base href="${pageContext.request.contextPath }"> <title>文件上传</title> </head> <body> <h3>单文件上传</h3> <form action="/file/upload" method="post" enctype="multipart/form-data"> <label>编号:</label><input type="text" name="id" readonly="readonly" value="${param.id}"/><br/> <label>图片:</label><input type="file" name="imgFile"/><br/> <input type="submit" value="上传图片"/> </form> <br> <h3>多文件上传</h3> <form method="post" action="/file/uploads" enctype="multipart/form-data"> <input type="file" name="files" multiple> <button type="submit">上传</button> </form> </body> </html>
3. 运行测试
如下图,多文件上传选择了10个文件,而单文件上传功能使用ctrl+选择是无效的,只能选择当个文件。
接下测试多文件上传是否能在本地查看
注意事项❗
选择多张图片的时候需要注意设置文件上传的大小,还有数据库存储图片的字段的类型长度是否超过,这都会影响文件是否能上传成功。因为多张图片的空间累计需要更多的空间,通过避免图片名称过长,查看存储该字段的长度是否能装的下。