?
本文檔使用 PHP中文網(wǎng)手冊 發(fā)布
Spring Portlet MVC和Web MVC一樣,也支持multipart來處理portlet中的文件上傳。
插件式的PortletMultipartResolver
提供了對multipart的支持,
它在org.springframework.web.portlet.multipart
包里。
Spring提供了PortletMultipartResolver
來和
Commons FileUpload
一起使用。余下的篇幅會介紹文件上傳的支持。
缺省情況下,Spring Portlet是不會處理multipart的,如果開發(fā)人員需要處理multipart,
就必須在web應(yīng)用的context里添加一個multipart解析器,然后,
DispatcherPortlet
會在每個請求里檢查是否帶有multipart。
如果沒找到,請求會繼續(xù),如果找到了multipart,在context中聲明的
PortletMultipartResolver
會被調(diào)用。接著,
在請求里的multipart屬性會和其它的屬性一樣被處理。
任何已配置的PortletMultipartResolver
bean必須
使用下列id(或名稱):"PortletMultipartResolver
" 。
如果你已經(jīng)定義了你的PortletMultipartResolver
為任何其他名稱,
哪么DispatcherPortlet
將找不到你的
PortletMultipartResolver
,并因此沒有multipart的支持。
下面的例子介紹了
CommonsPortletMultipartResolver
的使用:
<bean id="portletMultipartResolver"
class="org.springframework.web.portlet.multipart.CommonsPortletMultipartResolver">
<!-- 一個屬性;以byte為單位的最大文件長度 -->
<property name="maxUploadSize" value="100000"/>
</bean>
當(dāng)然為了使multipart解析器能夠工作,必須把合適的jar放到類路徑里。對于
CommonsMultipartResolver
來說,需要
commons-fileupload.jar
。注意,必須使用至少1.1
版本的Commons FileUpload,因?yàn)橐郧暗陌姹静恢С諮SR-168應(yīng)用。
現(xiàn)在你已經(jīng)看到如何設(shè)置Portlet MVC來處理multipart請求,接下來我們
討論它的使用。當(dāng)DispatcherPortlet
檢測到
multipart時,它會激活在context里聲明的解析器,并把請求交給它。然后解析器
把當(dāng)前的ActionRequest
放到支持文件上傳的
MultipartActionRequest
中。通過
MultipartActionRequest
,可以得到
請求包含的multipart信息,并且在控制器里訪問multipart文件。
注意,不能從RenderRequest
接收到multipart
文件,而只能從ActionRequest
里。
在 PortletMultipartResolver
處理完后,
請求會繼續(xù)被處理。你需要創(chuàng)建一個帶有上傳字段的表單來使用它(見下面),Spring會
把文件綁定在你的表單上(支持對象)。為了讓用戶上傳文件,必須創(chuàng)建一個(JSP/HTML)的表單:
<h1>Please upload a file</h1> <form method="post" action="<portlet:actionURL/>" enctype="multipart/form-data"> <input type="file" name="file"/> <input type="submit"/> </form>
如你所見,我們在bean的屬性后面創(chuàng)建名為“File”的字段
用來容納 byte[]
。加上了編碼屬性( enctype="multipart/form-data"
),
讓瀏覽器知道怎樣來編碼multipart字段(切記?。?。
和其它那些不會自動轉(zhuǎn)化為字符串或原始類型的屬性一樣,為了把二進(jìn)制數(shù)據(jù)放到對象
里,必須注冊一個使用 PortletRequestDataBinder
的自定義的編輯器?,F(xiàn)成有好幾個編輯器可以用來處理文件并把結(jié)果放到對象上。
StringMultipartFileEditor
能夠把文件轉(zhuǎn)換成字符串
(使用用戶定義的字符集),ByteArrayMultipartFileEditor
能夠把文件轉(zhuǎn)換成字節(jié)數(shù)據(jù)。他們的功能和
CustomDateEditor
一樣。
所以,為了能夠使用表單來上傳文件,需要聲明解析器,映射到處理這個bean的控制器的映射以及控制器。
<bean id="portletMultipartResolver" class="org.springframework.web.portlet.multipart.CommonsPortletMultipartResolver"/> <bean id="portletModeHandlerMapping" class="org.springframework.web.portlet.handler.PortletModeHandlerMapping"> <property name="portletModeMap"> <map> <entry key="view" value-ref="fileUploadController"/> </map> </property> </bean> <bean id="fileUploadController" class="examples.FileUploadController"> <property name="commandClass" value="examples.FileUploadBean"/> <property name="formView" value="fileuploadform"/> <property name="successView" value="confirmation"/> </bean>
接著,創(chuàng)建控制器以及實(shí)際容納這個文件屬性的類。
public class FileUploadController extends SimpleFormController { public void onSubmitAction( ActionRequest request, ActionResponse response, Object command, BindException errors) throws Exception { // cast the bean FileUploadBean bean = (FileUploadBean) command; // let's see if there's content there byte[] file = bean.getFile(); if (file == null) { // hmm, that's strange, the user did not upload anything } // do something with the file here } protected void initBinder( PortletRequest request, PortletRequestDataBinder binder) throws Exception { // to actually be able to convert Multipart instance to byte[] // we have to register a custom editor binder.registerCustomEditor(byte[].class, new ByteArrayMultipartFileEditor()); // now Spring knows how to handle multipart object and convert } } public class FileUploadBean { private byte[] file; public void setFile(byte[] file) { this.file = file; } public byte[] getFile() { return file; } }
如你所見,FileUploadBean
有一個類型是
byte[]
的屬性來容納文件??刂破髯粤艘粋€自定義編輯器來
讓Spring知道如何把解析器發(fā)現(xiàn)的multipart轉(zhuǎn)換成指定的屬性。在這個例子里,
沒有對bean的 byte[]
屬性進(jìn)行任何操作,但實(shí)際上,你可以做任
何操作(把它存到數(shù)據(jù)庫里,把它電郵出去,或其它)
下面是一個例子,文件直接綁定在的一個(表單支持)對象上的字符串類型屬性上面:
public class FileUploadController extends SimpleFormController { public void onSubmitAction( ActionRequest request, ActionResponse response, Object command, BindException errors) throws Exception { // cast the bean FileUploadBean bean = (FileUploadBean) command; // let's see if there's content there String file = bean.getFile(); if (file == null) { // hmm, that's strange, the user did not upload anything } // do something with the file here } protected void initBinder( PortletRequest request, PortletRequestDataBinder binder) throws Exception { // to actually be able to convert Multipart instance to a String // we have to register a custom editor binder.registerCustomEditor(String.class, new StringMultipartFileEditor()); // now Spring knows how to handle multipart objects and convert } } public class FileUploadBean { private String file; public void setFile(String file) { this.file = file; } public String getFile() { return file; } }
當(dāng)然,最后的例子在上傳文本文件時才有(邏輯上的)意義(在上傳圖像文件時,它不會工作)。
第三個(也是最后一個)選項是,什么情況下需要直接綁定在(表單支持)對象的
MultipartFile
屬性上。在以下的情況,不需要注冊自定義的屬性編輯器,因?yàn)椴恍枰愋娃D(zhuǎn)換。
public class FileUploadController extends SimpleFormController { public void onSubmitAction( ActionRequest request, ActionResponse response, Object command, BindException errors) throws Exception { // cast the bean FileUploadBean bean = (FileUploadBean) command; // let's see if there's content there MultipartFile file = bean.getFile(); if (file == null) { // hmm, that's strange, the user did not upload anything } // do something with the file here } } public class FileUploadBean { private MultipartFile file; public void setFile(MultipartFile file) { this.file = file; } public MultipartFile getFile() { return file; } }