[置頂] 詳細闡述Web開發中的圖片上傳問題
來源:程序員人生 發布時間:2015-03-04 08:32:39 閱讀次數:5350次
Web開發中,圖片上傳是1種極為常見的功能。但是呢,每次做上傳,都花費了很多時間。 1個“小功能”花費我這么多時間,真心不愉快。
So,要得認真分析下緣由。
1.在最初學習Java Web開發的時候,經驗不足,屬于能力問題,比如對技術認識不到位。
2.圖片上傳是1類問題,而不是1個問題。
比如,大家都會做飯,但每一個人自己做飯是有不同的。做了1個人吃、1家人吃、喜事待客做好幾桌,是不同的問題。
一樣的,圖片上傳,是上傳1張還是多張,前真個用戶體驗如何,后端邏輯處理是不是正確,圖片存儲是不是可靠。
本文主要探討這個問題。
3. 有些情況,真不是我的問題。
比如,前端上傳組件是他人寫的,1會這樣做,1會那樣做,后端不斷改。
比如,代碼本來都不是我寫的,是由于需求變化了,我接手了,然后自己改。
-------------------------------------------------------------------------
下面,重點探討第2個緣由,技術問題。
a.上傳單個圖片
html寫個file類型的input,form設置1下,enctype="multipart/form-data"。
后端寫個方法處理下就好,扼要2點,1是用@RequestParam MultipartFile 接收1個文件,2是用FileUtils復制臨時文件到目標文件。
@RequestMapping(value = "oneFileUpload", method = RequestMethod.POST)
public String uploadLoginSplash(HttpServletRequest request, @RequestParam("file") MultipartFile file)
throws IOException {
if (!file.isEmpty()) {
String realPath = request.getSession().getServletContext().getRealPath(SPLASH);
// 這里沒必要處理IO流關閉的問題,由于FileUtils.copyInputStreamToFile()方法內部會自動把用到的IO流關掉,我是看它的源碼才知道的
FileUtils.copyInputStreamToFile(file.getInputStream(), new File(realPath, SPLASH_JPG));
}
return "manager/setting/settingManager";
}
b. 上傳多個圖片。 方法1: 定義多個file,后端用數組接收
@RequestParam("file") CommonsMultipartFile[] files。
1種比較靈活的方式是,寫JS方法,點擊“添加”和“刪除”,可以選擇增加上傳圖片的“上傳框”。
這類方式,我沒有去實踐,在CSDN上看到了1篇不錯的帖子,屬于看了但沒有去實踐。
方法2:
使用圖片上傳組件,相比方法1,更加靈活,但也有缺點,后端接收不能直接使用數組CommonsMultipartFile[] files,我嘗試了不太行。
前端上傳組件,嘗試的有webuploader,可以1次性選擇多張圖片,但是分批上傳的。
尼瑪,百度了下,原來是百度團隊弄的,怪不得看起來用起來,好高端大氣的模樣。
官網:http://fex-team.github.io/webuploader/
最早用的是,dropzone,感覺還行,但是沒有百度的看起來美觀,1次性可以選擇多張圖片,但1次性全部上傳。
官網:http://www.dropzonejs.com/
最早的最早,某個同事用的是jquery的上傳組件,印象中是的。
后端處理多張圖片的代碼,比較通用的。
@RequestMapping("/idCardImageUpload")
public void idCardImageUpload(HttpServletRequest request,
HttpServletResponse response) throws IllegalStateException,
IOException {
// 創建1個通用的多部份解析器
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(
request.getSession().getServletContext());
String finalFileName="";
// 判斷 request 是不是有文件上傳,即多部份要求
if (multipartResolver.isMultipart(request)) {
// 轉換成多部份request
MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;
// 獲得request中的所有文件名
Iterator<String> iter = multiRequest.getFileNames();
while (iter.hasNext()) {
// 獲得上傳文件
MultipartFile file = multiRequest.getFile(iter.next());
if (file != null) {
// 獲得當前上傳文件的文件名稱
String fileName = file.getOriginalFilename();
// 如果名稱不為“”,說明該文件存在,否則說明該文件不存在
if (StringUtils.isNotEmpty(fileName)) {
String[] strs = fileName.split(".");
String fileExtention="png";
// 重命名上傳后的文件名
if(strs.length >=2){
fileExtention=strs[strs.length⑴];
}
try {
fileName = AES.Encrypt(fileName, DateFormatUtil
.format(new Date(), "yyyyMMddHHmmssSSS")
.substring(1))+"."+fileExtention;
finalFileName +=fileName+",";
// 定義上傳路徑
String imagePath = (String) BasePropertyConfigurer
.getContextProperty("idCardImageUploadPath");
String path = imagePath + fileName;
File localFile = new File(path);
file.transferTo(localFile);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
JSONObject jsonObj = new JSONObject();
response.setContentType("text/html;charset=UTF⑻");
jsonObj.put("success", true);
jsonObj.put("fileName",finalFileName);
returnJsonObject(response, jsonObj);
}
}
--------------------------------------------------------------------------------------------
上面介紹了緣由,然后重點論述了前后真個組件和實踐方法,下面回歸“圖片上傳問題”的本質,即流程問題。
圖片上傳流程第1步:通過上傳組件,選擇1張或多張圖片。
第2步:肯定上傳,把圖片傳到后端,后端接收圖片,保存到某個位置。
第3步:前端提交表單,包括圖片的名字等。
這個問題有點復雜,再補充幾點:
第1:上傳是可以同步的,也能夠是異步的。
比如通過form提交到后端,也能夠是通過
jquery等插件AJAX提交。
異步提交的時候,需要后端“回顯圖片信息”,比如圖片的名字、圖片的URL。
第2:是不是允許圖片存儲位置,有“臟數據”,即沒有實際價值的圖片。
比如,1個用戶選擇了圖片,上傳到了后端,但是表單可能沒有提交。
如果,直接把用戶的圖片,放到實際的存儲位置,就有臟數據了,但不影響圖片的展現。
另外1種方式是,用戶上傳的圖片,先存到1個特定的臨時位置,用戶肯定上傳圖片后,把這里的圖片移動到,實際的存儲位置。
第3:圖片信息存到
數據庫。
個人覺得,只存儲圖片的名字比較好,至于路徑,存到
數據庫以后,會非常不靈活。
前端展現圖片,自定義url路徑,比如/image/a.jpg,后端把/image路徑映照到實際的圖片位置。
第4:圖片的名字。
把用戶上傳時的名字,作為實際存儲的圖片名字不好,1是中文容易出問題,2是不能保證唯1性,會存在覆蓋的可能性。
個人覺得,圖片的名字用時間+隨機數等方式生成唯1的名字,比如abcd.jpg。
這個時候需要注意,圖片的后綴,需要從用戶上傳的圖片名字解析出來,比如從“小雷FansUnion.png”解析出后綴".png",把
“小雷FansUnion.gif”存為“abcd.png”可能沒法正常顯示。
第5:圖片上傳也能夠使用云服務。
2014年春,做ITFriend的時候,用的是“美圖秀秀的圖片上傳組件”。云服務用著還是不錯的,上傳以后,可以立即進行“美化”“涂鴉”等操作。
終究,再保存到
數據庫。
第6:圖片存儲
也能夠使用云服務。。 個人覺得,圖片1定要存儲到Tomcat等服務器的外部。有的人為了方便,把圖片存儲到Tomcat的webapps目錄,這樣比較危險,tomcat重啟-重新部署,可能會把圖片給弄丟了。
存儲到硬盤等外部,做個圖片要求映照就好。
還有1種方式,圖片存儲也使用“云存儲”,又拍云用著還湊合。
-------------------------------------------------
總結,圖片上傳實際上是個很復雜的問題。
沒有足夠經驗,不懂實際需求的開發者,進度會估計不準。
參考資料
http://fex-team.github.io/webuploader/
http://www.dropzonejs.com/
http://blog.csdn.net/a1314517love/article/details/24183273
秒針工作時,BrandCenter項目積累
朋來谷工作時,ITFriend項目積累
1起好工作時,p2p項目積累
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈