javascript
SpringMVC+uploadify文件上传
前言
準(zhǔn)備籌劃一個(gè)自己的個(gè)人網(wǎng)站,初步的架構(gòu)設(shè)計(jì)采用SSH(Spring-MVC,Spring,Hibernate),在這里
順便記錄一下設(shè)計(jì)和開(kāi)發(fā)過(guò)程,以備參考。后續(xù)會(huì)陸續(xù)更新文檔,如有任何問(wèn)題,歡迎各位不吝指出,共
同學(xué)習(xí)。
環(huán)境
開(kāi)發(fā)環(huán)境 版本| eclipse | 4.3.2 |
| maven | 3.2.1 |
| Spring-MVC | 3.2.3.RELEASE |
| Spring | Spring |
| Hibernate | 3.2.5 |
文件上傳是很多項(xiàng)目都會(huì)使用到的功能,SpringMVC當(dāng)然也提供了這個(gè)功能。不過(guò)本人不建議在項(xiàng)目中
通過(guò)form表單來(lái)提交文件上傳,這樣做的局限性很大。對(duì)于文件上傳等類似的功能,推薦使用第三方的
插件(或者自己寫的插件)來(lái)實(shí)現(xiàn),這樣可以減輕服務(wù)端的壓力,同時(shí)呈現(xiàn)的頁(yè)面效果也會(huì)更好,而且
可插拔,擴(kuò)展性好。
在這里使用AJAX來(lái)上傳文件,為了方便,使用了第三方的插件uploadify(http://www.uploadify.com/?),
這個(gè)插件展示效果很好,還提供了豐富的功能,在下面的內(nèi)容中會(huì)簡(jiǎn)單介紹,有興趣的朋友可以到官網(wǎng)
去看下文檔,簡(jiǎn)單易用。
這里依然借助了SpringMVC的文件上傳功能,不過(guò)十三哥建議還是不要這樣做,這里純粹是為了介紹
SpringMVC的文件上傳而已。
還是希望能使用完整的前后端結(jié)合的文件上傳插件,把文件上傳的功能獨(dú)立出來(lái)。這樣頁(yè)面上就只顯示
一個(gè)已上傳的文件在服務(wù)端的保存地址,這個(gè)地址對(duì)應(yīng)于數(shù)據(jù)庫(kù)表中的URL字段。這樣顯示文件列表的
時(shí)候,服務(wù)端也只是從表中取出一系列的URL,再交由讀文件的插件去讀文件,這將會(huì)是非常好的一個(gè)
設(shè)計(jì)了。
使用SpringMVC的文件上傳功能,需要引入相應(yīng)的jar包,配置文件解析器。
【添加處理文件上傳的jar包】
pom.xml添加commons-io和commons-fileupload的依賴
<!-- 文件上傳 begin--> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.4</version> </dependency> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3</version> </dependency> <!-- 文件上傳 end-->
【springMVC-servlet.xml配置文件解析器】
<!-- SpringMVC上傳文件時(shí),處理文件的解析器,還可以配置文件的大小和異常處理--> <!-- 但是在后端配置文件的大小是不明智的,一般前端的上傳文件插件中都提供了這個(gè)功能, 所以在前端設(shè)置會(huì)更好--> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>另外,大家也會(huì)發(fā)現(xiàn),SpringMVC的Resolver(解析器)是個(gè)很關(guān)鍵的東西,需要什么樣的處理,就引入
什么樣的解析器就行了。
【Controller代碼】
package com.xbs.ready.ssh.controller;import com.alibaba.fastjson.JSON; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartHttpServletRequest;/*** 文件上傳的Controller** @author ssg*/ @Controller @RequestMapping("upload") public class FileUploadController { private static final String FILE_PATH = "C:/uploaddir"; @RequestMapping(value = "one", method = RequestMethod.POST) @ResponseBody public String uploadFile(HttpServletRequest request, HttpServletResponse response) throws IOException { //String fileName = (String)request.getAttribute("filename"); MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; Iterator<String> fileNames = multipartRequest.getFileNames(); MultipartFile multipartFile = multipartRequest.getFile(fileNames.next()); //如果使用firebug,或者chrome的開(kāi)發(fā)者工具,可以看到,這個(gè)文件上傳工具發(fā)送了兩個(gè)文件名 //分別是:name="Filedata"; filename="AVScanner.ini" //用這兩個(gè)文件名獲得文件內(nèi)容都可以,只不過(guò)第一個(gè)沒(méi)有后綴,需要自己處理 //第二個(gè)是原始的文件名,但是這個(gè)文件名有可能是上傳文件時(shí)的全路徑 //例如 C:/testssh/a.log,如果是全路徑的話,也需要處理 String fileAlias = multipartFile.getName(); System.out.println("Spring MVC獲得的文件名:" + fileAlias); //獲得文件原始名稱 String name = multipartFile.getOriginalFilename(); String filePath = FILE_PATH + "/" + name; saveFile(filePath, multipartFile.getBytes()); Map<String, String> resultMap = new HashMap<String, String>(5); resultMap.put("result", "success"); resultMap.put("filePath", filePath); return JSON.toJSONString(resultMap); } //保存文件的方法 public void saveFile(String filePath, byte[] content) throws IOException { BufferedOutputStream bos = null; try { File file = new File(filePath); //判斷文件路徑是否存在 if (!file.getParentFile().exists()) { //文件路徑不存在時(shí),創(chuàng)建保存文件所需要的路徑 file.getParentFile().mkdirs(); } //創(chuàng)建文件(這是個(gè)空文件,用來(lái)寫入上傳過(guò)來(lái)的文件的內(nèi)容) file.createNewFile(); bos = new BufferedOutputStream(new FileOutputStream(file)); bos.write(content); } catch (FileNotFoundException e) { throw new FileNotFoundException("文件不存在。"); } finally { if (null != bos) { bos.close(); } } }}【HTML代碼】
html文件路徑:.../webapp/views/upload.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <link rel="stylesheet" type="text/css" href="http://localhost:8080/sshdemo/static/css/uploadify.css"> <script type="text/javascript" src="http://localhost:8080/sshdemo/static/js/jquery-1.7.2.min.js"></script> <script type="text/javascript" src="http://localhost:8080/sshdemo/static/js/jquery.uploadify.js"></script> <meta name="viewport" content="width=device-width"> <title>文件上傳</title> <script type="text/javascript"> $(document).ready(function() { fileUpload(); }); function fileUpload() { $("#upload").uploadify({ "uploader": "http://localhost:8080/sshdemo/upload/one", "method": "post", "progressData": "percentage", "swf": "http://localhost:8080/sshdemo/static/flash/uploadify.swf", "buttonText": "選擇要上傳的文件", "multi": true, "fileSizeLimit": "100KB", "queueSizeLimit": 5, "successTimeout": 600, "onUploadSuccess": function(file, data, response) { alert('The file ' + file.name + ' was successfully uploaded with a response of ' + response + ':' + data); }, "onUploadError": function(file, errorCode, errorMsg, errorString) { alert('The file ' + file.name + ' could not be uploaded: ' + errorString); }, "onSelectError": function() { alert('The file ' + file.name + ' returned an error and was not added to the queue.'); } }); } </script> </head> <body> <form enctype="multipart/form-data"> <input id="upload" type="file" /> </form> </body> </html>
訪問(wèn)
訪問(wèn)路徑:http://localhost:8080/sshdemo/views/upload.html
(或者通過(guò)訪問(wèn)Controller,然后跳轉(zhuǎn)回這個(gè)頁(yè)面,不過(guò)不建議這樣做,盡量不去
打擾服務(wù)端)
uploadify介紹
這里只簡(jiǎn)要介紹上面使用的幾個(gè)參數(shù),其余的可以參照官方文檔(http://www.uploadify.com/documentation/?)
uploader:服務(wù)端處理上傳文件的路徑
"uploader": "http://localhost:8080/sshdemo/upload/one"method:訪問(wèn)方式,post,get(這個(gè)訪問(wèn)方式要與服務(wù)的訪問(wèn)方式一致,否則405)
"method": "post"progressData:上傳進(jìn)度,有percentage(百分比)和speed(進(jìn)度條)兩個(gè)值
"progressData": "percentage"swf:動(dòng)畫文件的路徑,因?yàn)橐菔旧蟼鬟M(jìn)度,所以需要?jiǎng)赢?#xff08;這個(gè)文件在官網(wǎng)的zip包里有,可以直接
使用)
"swf": "http://localhost:8080/sshdemo/static/flash/uploadify.swf"buttonText:上傳按鈕的名字
"buttonText": "選擇要上傳的文件"multi:是否可一次上傳多個(gè)文件,true:可以,false:不可以(默認(rèn)false)
"multi": truefileSizeLimit:文件大小的限制(這里指單個(gè)文件),單位可以有B,KB,MB,和GB,默認(rèn)是KB,
不過(guò)建議顯式指定,方便理解;這個(gè)參數(shù)設(shè)置也可以代替在后臺(tái)的配置文件中指定可上傳文件的大小
"fileSizeLimit": "100KB"queueSizeLimit:可上傳文件的個(gè)數(shù),如果不指定那么沒(méi)有上限,建議指定的好
"queueSizeLimit": 5successTimeout:上傳文件后,多長(zhǎng)時(shí)間服務(wù)端沒(méi)有響應(yīng)就意為上傳成功,單位是秒(這時(shí)可能服務(wù)端
出錯(cuò)了,但是服務(wù)端處理的時(shí)間超過(guò)了這里設(shè)置的時(shí)間,那么插件會(huì)認(rèn)為上傳成功了)
"successTimeout": 60onUploadSuccess:上傳文件成功后,觸發(fā)的事件
@Param file:上傳成功的那個(gè)文件對(duì)象 @Param data:服務(wù)端返回的數(shù)據(jù),這個(gè)例子中返回的是JSON數(shù)據(jù) @Param response:服務(wù)端的響應(yīng),true 或者 false(注意:如果服務(wù)端在超過(guò)了 successTimeout之后返回了false,那么插件依然會(huì)返回true) "onUploadSuccess": function(file, data, response) {alert('The file ' + file.name + ' was successfully uploaded with a response of ' + response + ':' + data); }onUploadError:上傳文件失敗后,觸發(fā)的事件
@Param file:上傳的文件對(duì)象 @Param errorCode:錯(cuò)誤代碼(這個(gè)代碼是插件返回的,不是服務(wù)端) @Param errorMsg:錯(cuò)誤信息(插件返回的錯(cuò)誤信息) @Param errorString:詳細(xì)的錯(cuò)誤信息"onUploadError": function(file, errorCode, errorMsg, errorString) {alert('The file ' + file.name + ' could not be uploaded: ' + errorString); }onSelectError:選擇上傳文件出錯(cuò)時(shí)(例如 queueSizeLimit=5,但是選擇了6個(gè)文件),可以觸發(fā)這個(gè)
事件;文件上傳失敗時(shí),也可以觸發(fā)這個(gè)事件
@Param file:上傳的文件對(duì)象 @Param errorCode:錯(cuò)誤代碼(QUEUE_LIMIT_EXCEEDED,FILE_EXCEEDS_SIZE_LIMIT,ZERO_BYTE_FILE,INVALID_FILETYPE) @Param errorMsg:錯(cuò)誤信息 "onSelectError": function() {alert('The file ' + file.name + ' returned an error and was not added to the queue.'); }這里就介紹這幾個(gè)參數(shù)了,官網(wǎng)還有好多參數(shù),觸發(fā)事件,方法等,等以后用到了再介紹吧。
【問(wèn)題說(shuō)明】
由于沒(méi)有保存之前的錯(cuò)誤信息,所以暫時(shí)沒(méi)有什么問(wèn)題要解決了,要個(gè)各位有問(wèn)題
的話,可以提出來(lái)。
總結(jié)
以上是生活随笔為你收集整理的SpringMVC+uploadify文件上传的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: C指针原理(14)-C指针基础
- 下一篇: C指针原理(15)-C指针基础