JavaWeb方向編程過程當中,實現圖片上傳有三種方式:css
一、傳統的基於springMVC的MultipartFile類實現圖片上傳。前端
二、基於Ajax的圖片上傳。jquery
三、基於Base64壓縮的圖片上傳。linux
此方法的優勢是能夠將圖片和其餘的表單元素一塊兒提交到服務器,服務器接受到的圖片其實已經存儲於容器的臨時文件中,進行文件拷貝工做比較簡單。web
缺點是沒法及時看到圖片上傳的預覽效果,圖片一旦選擇錯誤只能從新提交。ajax
注:紅色代碼爲關鍵代碼。spring
<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>
建立名爲config.properties的配置文件,而且再其中配置圖片上傳物理路徑。注意window和linux的寫法不一樣。
數據庫
**此配置內容在springboot結構中的application.properties文件中配置**編程
file.location.path=d:/upload
**此配置文件在springboot中不須要配置 - 「習慣大於配置」**json
<?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>
如果一次上傳多個文件,須要使用註解@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"; } } }
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; } }
這種方式同第一種方式同樣都是使用multipart/form-data方式上傳,服務器端一樣使用springMVC(springboot)實現因此只有頁面代碼不一致,其餘代碼(二、三、四、5)同上。
該方式前端使用的是jQuery的jquery.fileupload.js插件來實現。詳見大神文章:http://www.javashuo.com/article/p-rplzpedd-t.html
**順序不能錯誤**
<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>
**不須要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
$(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實現圖片上傳其實就是在瀏覽器端先將圖片轉換成字符串,而後將表明圖片的字符串傳輸到服務器進行存儲。須要顯示的時候能夠將字符串寫入<img src="">直接顯示。
該圖片上傳的方式比較簡單,且沒有其餘的例如跨域提交、頭文件等問題。可是其編碼後的字符串大小遠遠大於實際的圖片大小。因此只適合上傳小尺寸的圖片,例如用戶頭像等。
$("#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');
} });
一、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/"); } }
二、若是使用springMVC的SSM框架,則能夠在tomcat的service.xml文件中直接配置虛擬路徑,代碼以下:
<Context docBase="/Users/David/upload" path="/image" reloadable="true"/>
參考資料: