一、圖片上傳介紹
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的插件
**順序不能錯誤**
<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{ width: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; width: 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="width: 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"/>
參考資料:
https://www.imooc.com/article/27804