主页 > 其他  > 

SpringBoot简单优雅实现图片上传功能(超详细)

SpringBoot简单优雅实现图片上传功能(超详细)

文章目录 前言技术栈项目目录前端实现index.htmlscript.js 后端实现MultipartFile 介绍配置文件实体类ControllerMapperService拦截器 测试结果展示


前言

最近有一个需求需要实现图片上传,因此,本人找到了一个可以快速实现该功能的插件mini-upload-form。在此记录分享一下使用过程。

mini-upload-form的Github跳转 将程序从github拉下后,前端页面index.html可简单修改后直接使用,我们的精力主要放在后端实现。

技术栈 jdk1.8.0_162maven-3.3.9mybatis-plus 项目目录

需将mini-upload-from中assets文件下的资源引入自己项目中。除外还需引入bootstrap和jquery。

前端实现 index.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <title>Mini Ajax File Upload Form</title> <!-- The main CSS file --> <link href="mini-upload-form/css/style.css" rel="stylesheet"/> <link href="bootstrap/css/bootstrap.css" rel="stylesheet"/> </head> <body> <div class="row"> <div class="col align-self-start"> <div><h4>上传照片:</h4></div> <div class="d-flex flex-row flex-wrap mb-5" id="upload-img-container"> <p>暂无</p> </div> </div> </div> <div class="row"> <div class="col align-self-start"> <form id="upload" method="post" action="/file/upload" enctype="multipart/form-data"> <div id="note" class="text-white"></div> <div id="drop"> 拖到此区域 <a>浏览本地</a> <input id="uploadFile" type="file" name="file" multiple/> </div> <ul> <!-- The file uploads will be shown here --> </ul> </form> <div class="col align-self-start"> </div> <div class="row"> <div class="col align-self-start"> <div class="text-center"> <a type="button" id="submit-file-btn" class="text-center btn btn-info text-white">提交</a> </div> </div> </div> </div> </div> <script src="js/jquery-1.11.3.js"></script> <script src="bootstrap/js/bootstrap.js"></script> <script src="mini-upload-form/js/jquery.knob.js"></script> <!-- jQuery File Upload Dependencies --> <script src="mini-upload-form/js/jquery.ui.widget.js"></script> <script src="mini-upload-form/js/jquery.iframe-transport.js"></script> <script src="mini-upload-form/js/jquery.fileupload.js"></script> <!-- Our main JS file --> <script src="mini-upload-form/js/script.js"></script> </body> </html> script.js

本文还实现了上传成功后回写到前端页面,所以需修改script.js添加提交成功后回调函数。

// Automatically upload the file once it is added to the queue var jqXHR = data.submit().success(function (result) { var status = result['code']; var fileUri = result['fileUri']; var fileId = result['fileId']; var originFileName = result['originFileName']; if (status!='200'){ data.context.addClass('error'); numError++; }else{ images.push(fileId) localStorage.setItem('cd_files', JSON.stringify(images)) numSuccess++; $("#upload-img-container>p:nth-child(1)").remove() const imageHTML = "<div style='width:100px;height:100px;margin:.5rem;text-align:center'>"+ "<image class='rounded' style='width:100%;height:100%' src="+staticServer + fileUri +" alt=>"+ "<p class='text-center text-muted ' style='word-wrap: break-word;'>"+originFileName+"</p></div>"; $("#upload-img-container").append(imageHTML) } updateNote(); }); // Update the note function updateNote() { if($('#note').length) $('#note').html('<span>' + numSuccess + '</span> 个成功上传.<br /><span id="note-error">' + numError + '</span> 个上传失败.' + (numError > 0 ? ' <a href="#" id="btn-retry"> (Retry all)</a>' : '')); } 后端实现 MultipartFile 介绍

MultipartFile是SpringMVC提供简化上传操作的工具类。

在不使用框架之前,都是使用原生的HttpServletRequest来接收上传的数据,文件是以二进制流传递到后端的,然后需要我们自己转换为File类。使用了MultipartFile工具类之后,我们对文件上传的操作就简便许多了。 MultipartFile接口方法

package org.springframework.web.multipart; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; import org.springframework.core.io.InputStreamSource; import org.springframework.core.io.Resource; import org.springframework.lang.Nullable; import org.springframework.util.FileCopyUtils; public interface MultipartFile extends InputStreamSource { //getName() 返回参数的名称 String getName(); //获取源文件的昵称 @Nullable String getOriginalFilename(); //getContentType() 返回文件的内容类型 @Nullable String getContentType(); //isEmpty() 判断是否为空,或者上传的文件是否有内容 boolean isEmpty(); //getSize() 返回文件大小 以字节为单位 long getSize(); //getBytes() 将文件内容转化成一个byte[] 返回 byte[] getBytes() throws IOException; //getInputStream() 返回InputStream读取文件的内容 InputStream getInputStream() throws IOException; default Resource getResource() { return new MultipartFileResource(this); } //transferTo(File dest) 用来把 MultipartFile 转换换成 File void transferTo(File var1) throws IOException, IllegalStateException; default void transferTo(Path dest) throws IOException, IllegalStateException { FileCopyUtils.copy(this.getInputStream(), Files.newOutputStream(dest)); } } 配置文件 # server server.port=8010 # datasource spring.datasource.url=jdbc:mysql://xxxx:3306/upload?characterEncoding=utf-8&useSSL=false spring.datasource.username=*** spring.datasource.password=**** spring.datasource.driver-class-name=com.mysql.jdbc.Driver # upload size setting spring.servlet.multipart.max-file-size=30MB spring.servlet.multipart.max-request-size=30MB file.upload.dir=D://upload file.visit.path=upload 实体类

图片存储实体类SysFile

@Data @Builder @TableName("sys_file") public class SysFile { private String fileId; private String mediaType; private String fileFormat; private String filePath; private String originalName; private Long fileSize; private Integer imageWidth; private Integer imageHeight; private String createUserId; private Date createDate; private String updateUserId; private Date updateDate; } Controller @RestController @RequestMapping("/file") public class FileUploadController { @Autowired private LocalStorageService localStorageService; @RequestMapping("/upload") public AjaxResult upload(@RequestParam("file") MultipartFile file) throws Exception { try { if (file.isEmpty()) { throw new RuntimeException("上传文件不能为空"); } return localStorageService.upload(file); } catch (Exception e) { e.printStackTrace(); return AjaxResult.error("文件上传失败"); } } } Mapper

SysFileMapper

@Mapper public interface SysFileMapper extends BaseMapper<SysFile> { } Service

SysFileService

public interface SysFileService extends IService<SysFile> { } @Service public class sysFileServiceImpl extends ServiceImpl<SysFileMapper, SysFile> implements SysFileService { }

LocalStorageService

@Slf4j @Service("localStorageService") public class LocalStorageService { @Autowired private SysFileService sysFileService; @Value("${file.upload.dir}") private String uploadDir; @Value("${file.visit.path:upload}") private String visitPath; private static final String[] ALLOW_FILE_TYPES = { "jpg", "jpeg", "png"}; public AjaxResult upload(MultipartFile file) throws Exception { String contentType = file.getContentType().toLowerCase(); boolean allowType = false; for (String allowFileType : ALLOW_FILE_TYPES) { if(contentType.contains(allowFileType)) { allowType = true; break; } } if (!allowType) { return AjaxResult.error("请上传正确的文件格式"); } String fileId = UUID.randomUUID().toString(); String subFolder = hashBy256(fileId); File destFolder = new File(uploadDir + File.separator + subFolder); if (!destFolder.exists()) { destFolder.mkdirs(); } String originalFilename = file.getOriginalFilename(); String fileExt = getFileType(originalFilename); String destFileName = fileId + "." + fileExt; File destFile = new File(uploadDir + File.separator + subFolder + File.separator + destFileName); log.info("file saved in: {}", destFile.getAbsoluteFile()); file.transferTo(destFile); String filePath = visitPath + File.separator + subFolder + File.separator + destFileName; String fileUri = transferPathAsImageUri(filePath); Long fileSize = file.getSize(); SysFile sysFile = SysFile.builder() .fileId(fileId) .filePath(filePath) .fileFormat(fileExt) .fileSize(fileSize) .mediaType(contentType) .originalName(originalFilename) .build(); sysFileService.save(sysFile); return AjaxResult.success() .put("fileId", fileId) .put("filePath", filePath) .put("originFileName", originalFilename) .put("fileName", destFileName) .put("fileUri", fileUri); } private String getFileType(String originalFilename){ int extPos = originalFilename.lastIndexOf("."); if (extPos != -1) { return originalFilename.substring(extPos + 1); } throw new RuntimeException("未知类型"); } public static String hashBy256(String str) { String s = Integer.toHexString(Math.abs(str.hashCode()) % 256).toUpperCase(); if (s.length() == 1) { s = "0" + s; } return s; } public static String transferPathAsImageUri(String fileServerPath) { if (!StringUtils.hasLength(fileServerPath)) { return null; } return "/" + fileServerPath.replaceAll("\\\\", "/"); } } 拦截器

ResourceConfig,该拦截器用于上传后回写到界面

@Configuration public class ResourceConfig implements WebMvcConfigurer { @Value("${file.visit.path:upload}") private String visitPath; @Value("${file.upload.dir}") private String resourceDir; @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/" + visitPath + "/**").addResourceLocations("file:" + resourceDir + "/"); } } 测试结果展示

前端界面


标签:

SpringBoot简单优雅实现图片上传功能(超详细)由讯客互联其他栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“SpringBoot简单优雅实现图片上传功能(超详细)