SpringMvc非同步圖片上傳回顯(使用jersey上傳到另一臺伺服器)
在之前的文章中已經介紹過springMvc的檔案上傳,springMvc檔案上傳
場景介紹
在本篇部落格中主要介紹使用springMvc進行圖片的上傳
功能需求:在很多網站中都有上傳使用者頭像的功能,上傳之後就會立刻在頁面上顯示出來,這邊就是採用的非同步的方式,並且在實際應用中最好有一個單獨的伺服器作為圖片伺服器,因為載入圖片的時候通常會佔據較大的頻寬,與應用程式伺服器放在一塊的話,影響應用程式伺服器的效能,在這裡由於沒有兩臺伺服器,所以會在一臺電腦上部署兩個tomcat,這樣當圖片上傳後,會先將圖片通過jersey上傳到另一臺伺服器下,然後將路徑儲存到資料庫中
準備
在同一臺電腦上部署兩臺tomcat
第一步 準備好tomcat壓縮包,解壓後,修改server.xml中的三個埠(不要與其他應用程式的埠號衝突,例如SVN的8443),這三個埠號預設是8005,8009,8080,將他們修改為別的
第二步 因為jersey是需要將圖片寫入到伺服器中的,所以需要配置圖片上傳的tomcat允許使用者用過post或者put向伺服器寫資料(預設是不允許的),配置方式如下
<!--tomcat中的web.xml,主要設定readOnly為false-->
<servlet>
<servlet-name>default</servlet-name >
<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>0</param-value>
</init-param>
<init-param>
<param-name >readonly</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>listings</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
準備好jersey的jar包
使用springMvc上傳圖片
檔案上傳解析器的配置
與上傳檔案一樣,需要配置一個檔案上傳的解析器,注意在配置的時候,圖片解析器的id必須為multipartResolver
<!-- 配置圖片上傳的解析器 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 單位是位元組,這裡設定成10MB,即1024*1024 -->
<property name="maxUploadSize" value="10485760"></property>
<property name="uploadTempDir" value="/WEB-INF/temp"></property>
</bean>
前端程式碼的編寫
因為是圖片上傳,所以我們可以將input標籤包裹在form表單裡,然後使用ajax直接提交表單到後臺,至於提交的其它的欄位,我們可以在控制器裡不管它們
注意
非同步上傳圖片的時候,需要在使用者點選選擇—>開啟檔案後,就通過ajax將圖片上傳到伺服器,所以需要監聽input type=‘file’的一個事件,這個事件就是onchange
<form id="jvForm" action="/back/brand/add.do" method="post" enctype="multipart/form-data">
...
<tr>
<td width="20%" class="pn-flabel pn-flabel-h"></td>
<td width="80%" class="pn-fcontent">
<img width="100" height="100" id="allImgUrl"/>
<input type="hidden" name="imgUrl" id="imgUrl"/>
<input type="file" onchange="uploadPic()" name="pic"/>
</td>
</tr>
...
</form>
在上傳檔案後,我們將圖片回顯到頁面上的img標籤上,並且將返回過來的imgUrl設定到隱藏域中,因為當用戶真正提交表單的時候,需要將圖片的路徑儲存到資料庫中,而當觸發的onchange事件時,只會將圖片上傳到伺服器,並將圖片的路徑返回過來,並不會儲存到資料庫,這就要求我們在提交的時候將imgUrl儲存
<script type="text/javascript">
function uploadPic(){
$("#jvForm").ajaxSubmit({
url:"/back/uploadPic.do",
dataType:"json",
type:"post",
success:function(data){
$("#allImgUrl").attr("src",data.url);
$("#imgUrl").val(data.path);
}
});
}
</script>
控制器的編寫
import org.apache.commons.io.FilenameUtils;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.Client;
@RequestMapping("/uploadPic.do")
public void uploadPic(MultipartFile pic, HttpServletResponse response) {
// 獲取檔案的相關資訊
// 檔案的名稱,使用uuid
String fileName = UUID.randomUUID().toString().replace("-", "");
// 獲取檔案的副檔名
String ext = FilenameUtils.getExtension(pic.getOriginalFilename());
// 要上傳的檔案的url,將其回顯到前臺進行展示
// 將其回顯到前端,在brand新增表單提交的時候,插入到資料庫中
String path = "babasport_images/" + fileName + "." + ext;
//Constants.IMAGE_SERVER http://localhost:8088/
String url = Constants.IMAGE_SERVER + path;
Client client = new Client();
WebResource resource = client.resource(url);
try {
resource.put(pic.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
JSONObject jo = new JSONObject();
jo.put("url", url);
jo.put("path", path);
response.setContentType("application/json;charset=UTF-8");
try {
response.getWriter().write(jo.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
注意事項
1. 返回的時候,是返回的json,所以一定要設定contentType
2. 圖片上傳的前端必須要設定enctype=”multipart/form-data”,以及用post
一個常見異常的解決
Failed to parse multipart request
org.apache.commons.fileupload.FileUploadException: Processing of multipart/form-data request failed. 、\localhost \_ \upload__3d7cf8b_11936276cf8__7ffd_00000011.tmp
需要重新設定一下檔案上傳時,commons.fileupload將上傳的檔案以流的形式將檔案寫到一個臨時資料夾中,現在這個檔案找不到了
解決方法:自己設定臨時資料夾,不用commons.fileupload預設的,在注入的時候注入uploadTempDir