一、图片上传介绍
JavaWeb方向编程过程中,实现图片上传有三种方式:
1、传统的基于springMVC的MultipartFile类实现图片上传。
2、基于Ajax的图片上传。
3、基于Base64压缩的图片上传。
二、springMVC图片上传(springboot通用)
此方法的优点是可以将图片和其他的表单元素一起提交到服务器,服务器接受到的图片其实已经存储于容器的临时文件中,进行文件拷贝工作比较简单。
缺点是无法及时看到图片上传的预览效果,图片一旦选择错误只能重新提交。
注:红色代码为关键代码。
1、页面代码
<form action="/upload" method="post" enctype="multipart/form-data"> 选择头像:<input type="file" name="file" accept="image/*" /> <br> 用户名字:<input type="text" name="userName"/> <br> <input type="submit" value="提交"> </form>
2、config.properties配置文件
创建名为config.properties的配置文件,并且再其中配置图片上传物理路径。注意window和linux的写法不同。
**此配置内容在springboot结构中的application.properties文件中配置**
file.location.path=d:/upload
3、spring-servlet.xml配置文件
**此配置文件在springboot中不需要配置 - “习惯大于配置”**
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!-- 设置使用注解的类所在的jar包 --> <context:component-scan base-package="org.lanqiao.service"/> <context:component-scan base-package="org.lanqiao.controller"/> <!--读取属性文件--> <context:property-placeholder location="classpath:config.properties" ignore-unresolvable="true"/> <!-- 注册HandlerMapping和HandlerAdapter组件 --> <mvc:annotation-driven/> <!-- 对静态资源文件的访问 支持访问WEB-INF目录 --> <mvc:default-servlet-handler/> <!-- 对转向页面的路径解析。prefix:前缀,suffix:后缀 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/" p:suffix=".jsp"/> <!--文件上传--> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="maxUploadSize" value="104857600"/> <property name="maxInMemorySize" value="4096"/> <property name="defaultEncoding" value="UTF-8"/> </bean> </beans>
4、controller代码
若是一次上传多个文件,需要使用注解@RequestParam("inputName") 指明该文件对应表单中的input标签的name属性。如果name都是同名的,可以使用MultipartFile [] 文件数组来接收
@Controller public class UserController { @Autowired UserService userService; @Value("${file.location.path}") private String fileLocation; @RequestMapping("/insert") public String insert(User user, MultipartFile file){ String uri = FileUpload.upload(file,"/upload",fileLocation); user.setFacePic(uri); int ret = userService.insertUser(user); if(ret > 0 ){ return "redirect:/get"; }else{ return "register"; } } }
5、上传工具类代码
public class FileUpload { /** * @param file 上传的文件 * @param path 文件的虚拟路径,例如 /upload * @param fileLocation 文件的物理路径,例如d:/upload * @return 文件的虚拟路径+文件名 * * fileName.lastIndexOf(".")为获取后缀名 * UUID.randomUUID()为获取唯一标识,保证文件的唯一性 */ public static String upload(MultipartFile file, String path, String fileLocation) { String fileFinishName = null; try { // 如果目录不存在则创建 File uploadDir = new File(fileLocation); if (!uploadDir.exists()) { uploadDir.mkdir(); } //获取源文件名称 String fileName = file.getOriginalFilename(); fileFinishName = UUID.randomUUID() + fileName.substring(fileName.lastIndexOf("."), fileName.length()); //上传文件到指定目录下 File uploadFile = new File(uploadDir + uploadDir.separator + fileFinishName); file.transferTo(uploadFile); } catch (Exception ex) { ex.printStackTrace(); } return path + "/" + fileFinishName; } }
三、基于Ajax的图片上传
这种方式同第一种方式一样都是使用multipart/form-data方式上传,服务器端同样使用springMVC(springboot)实现所以只有页面代码不一致,其他代码(2、3、4、5)同上。
该方式前端使用的是jQuery的jquery.fileupload.js插件来实现。详见大神文章:https://blog.csdn.net/qq_37936542/article/details/79258158
1、页面先一用jQuery的插件
下载地址:https://github.com/blueimp/jQuery-File-Upload
**顺序不能错误**
<script src="js/jquery-3.2.1.min.js"></script> <!-- jquery file upload相关js --> <script src="js/jquery.ui.widget.js"></script> <script src="js/jquery.iframe-transport.js"></script> <script src="js/jquery.fileupload.js"></script> <script src="js/jquery.fileupload-process.js"></script> <script src="js/jquery.fileupload-validate.js"></script>
2、HTML代码编写
**不需要form标签**
<style> /* input样式 */ #uploadImg{ display: none; } /* button样式 */ #chooseFile{ background: #93b6fc; } #uploadFile,#rechooseFile { display: none; background: #93b6fc; } #image{ 200px; height:200px; } /* 进度条样式 */ .bar { background-image: -webkit-linear-gradient(top,#5cb85c 0,#449d44 100%); background-image: -o-linear-gradient(top,#5cb85c 0,#449d44 100%); background-image: -webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#449d44)); background-image: linear-gradient(to bottom,#5cb85c 0,#449d44 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0); background-repeat: repeat-x; height: 20px; line-height: 20px; -webkit-box-shadow: inset 0 -1px 0 rgba(0,0,0,.15); box-shadow: inset 0 -1px 0 rgba(0,0,0,.15); -webkit-transition: width .6s ease; -o-transition: width .6s ease; transition: width .6s ease; } #progress { filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0); background-repeat: repeat-x; height: 20px; 0%; margin-bottom: 20px; overflow: hidden; background-color: #f5f5f5; border-radius: 4px; -webkit-box-shadow: inset 0 1px 2px rgba(0,0,0,.1); box-shadow: inset 0 1px 2px rgba(0,0,0,.1); margin-top: 20px; } </style> <body> <div class="jquery-fileupload"> <div class=""> <input id="uploadImg" type="file" name="uploadImg" multiple style="display: none" /> <button id="chooseFile">+选择文件</button> <button id="uploadFile">~开始上传</button> <button id="rechooseFile">+重新选择</button> </div> <div> <img id="image" src=""> </div> <div id="progress"> <div class="bar" style=" 0%;"></div> </div> </div> </body>
3、js代码
$(function() { $("#chooseFile").on("click", function() { $("#uploadImg").click(); }); $('#uploadImg').fileupload({ url : '/upload',//请求发送的目标地址 Type : 'POST',//请求方式 ,可以选择POST,PUT或者PATCH,默认POST //dataType : 'json',//服务器返回的数据类型 autoUpload : false, acceptFileTypes : /(gif|jpe?g|png)$/i,//验证图片格式 maxNumberOfFiles : 1,//最大上传文件数目 maxFileSize : 1000000, // 文件上限1MB minFileSize : 100,//文件下限 100b messages : {//文件错误信息 acceptFileTypes : '文件类型不匹配', maxFileSize : '文件过大', minFileSize : '文件过小' } }) //图片添加完成后触发的事件 .on("fileuploadadd", function(e, data) { //validate(data.files[0])这里也可以手动来验证文件格式和大小 //隐藏或显示页面元素 $('#progress .bar').css( 'width', '0%' ); $('#progress').hide(); $("#chooseFile").hide(); $("#uploadFile").show(); $("#rechooseFile").show(); //获取图片路径并显示 var url = getUrl(data.files[0]); $("#image").attr("src", url); //绑定开始上传事件 $('#uploadFile').click(function() { $("#uploadFile").hide(); jqXHR = data.submit(); //解绑,防止重复执行 $("#uploadFile").off("click"); }) //绑定点击重选事件 $("#rechooseFile").click(function(){ $("#uploadImg").click(); //解绑,防止重复执行 $("#rechooseFile").off("click"); }) }) //当一个单独的文件处理队列结束触发(验证文件格式和大小) .on("fileuploadprocessalways", function(e, data) { //获取文件 file = data.files[0]; //获取错误信息 if (file.error) { console.log(file.error); $("#uploadFile").hide(); } }) //显示上传进度条 .on("fileuploadprogressall", function(e, data) { $('#progress').show(); var progress = parseInt(data.loaded / data.total * 100, 10); $('#progress').css( 'width','15%' ); $('#progress .bar').css( 'width',progress + '%' ); }) //上传请求失败时触发的回调函数 .on("fileuploadfail", function(e, data) { console.log(data.errorThrown); }) //上传请求成功时触发的回调函数 .on("fileuploaddone", function(e, data) { alert(data.result); }) //上传请求结束后,不管成功,错误或者中止都会被触发 .on("fileuploadalways", function(e, data) { }) //手动验证 function validate(file) { //获取文件名称 var fileName = file.name; //验证图片格式 if (!/.(gif|jpg|jpeg|png|gif|jpg|png)$/.test(fileName)) { console.log("文件格式不正确"); return true; } //验证excell表格式 /* if(!/.(xls|xlsx)$/.test(fileName)){ alert("文件格式不正确"); return true; } */ //获取文件大小 var fileSize = file.size; if (fileSize > 1024 * 1024) { alert("文件不得大于一兆") return true; } return false; } //获取图片地址 function getUrl(file) { var url = null; if (window.createObjectURL != undefined) { url = window.createObjectURL(file); } else if (window.URL != undefined) { url = window.URL.createObjectURL(file); } else if (window.webkitURL != undefined) { url = window.webkitURL.createObjectURL(file); } return url; } });
四、基于Base64压缩的图片上传
图片的Base64 编码就是可以将一副图片数据编码成一串字符串,使用该字符串代替图像地址。例如:
基于Base64实现图片上传其实就是在浏览器端先将图片转换成字符串,然后将代表图片的字符串传输到服务器进行存储。需要显示的时候可以将字符串写入<img src="">直接显示。
该图片上传的方式比较简单,且没有其他的例如跨域提交、头文件等问题。但是其编码后的字符串大小远远大于实际的图片大小。所以只适合上传小尺寸的图片,例如用户头像等。
1、页面代码
$("#img").change(function (e) { var img = e.target.files[0]; var reader = new FileReader(); reader.readAsDataURL(img); reader.onload = function (e) { // ajax 上传图片 $.post("uploadPic", {img: e.target.result}, function (ret) { if (ret.img != '') { //显示图片 $('#showimg').attr("src", ret.imgUrl); } }, 'json');
} });
2、服务器接收到Base64字符串,就可以得到图片并且将图片直接存入数据库。这里不再描述。
五、配置图片访问路径
1、Springboot中可以使用下面的代码将虚拟路径/image/**下的图片映射成到D://盘下。
import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; /** * 图片绝对地址与虚拟地址映射 * 访问地址示例:http://localhost:8080/image/1.png */ @Configuration public class WebMvcConfig extends WebMvcConfigurationSupport { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { //windows //registry.addResourceHandler("/image/**").addResourceLocations("file:d://upload/"); //linux和mac registry.addResourceHandler("/image/**").addResourceLocations("file:/Users/David/upload/"); registry.addResourceHandler("/**").addResourceLocations("classpath:/static/"); } }
2、如果使用springMVC的SSM框架,则可以在tomcat的service.xml文件中直接配置虚拟路径,代码如下:
<Context docBase="/Users/David/upload" path="/image" reloadable="true"/>
参考资料: