?
このドキュメントでは、 php中國(guó)語(yǔ)ネットマニュアル リリース
Spring Portlet MVC和Web MVC一樣,也支持multipart來(lái)處理portlet中的文件上傳。
插件式的PortletMultipartResolver
提供了對(duì)multipart的支持,
它在org.springframework.web.portlet.multipart
包里。
Spring提供了PortletMultipartResolver
來(lái)和
Commons FileUpload
一起使用。余下的篇幅會(huì)介紹文件上傳的支持。
缺省情況下,Spring Portlet是不會(huì)處理multipart的,如果開(kāi)發(fā)人員需要處理multipart,
就必須在web應(yīng)用的context里添加一個(gè)multipart解析器,然后,
DispatcherPortlet
會(huì)在每個(gè)請(qǐng)求里檢查是否帶有multipart。
如果沒(méi)找到,請(qǐng)求會(huì)繼續(xù),如果找到了multipart,在context中聲明的
PortletMultipartResolver
會(huì)被調(diào)用。接著,
在請(qǐng)求里的multipart屬性會(huì)和其它的屬性一樣被處理。
任何已配置的PortletMultipartResolver
bean必須
使用下列id(或名稱):"PortletMultipartResolver
" 。
如果你已經(jīng)定義了你的PortletMultipartResolver
為任何其他名稱,
哪么DispatcherPortlet
將找不到你的
PortletMultipartResolver
,并因此沒(méi)有multipart的支持。
下面的例子介紹了
CommonsPortletMultipartResolver
的使用:
<bean id="portletMultipartResolver"
class="org.springframework.web.portlet.multipart.CommonsPortletMultipartResolver">
<!-- 一個(gè)屬性;以byte為單位的最大文件長(zhǎng)度 -->
<property name="maxUploadSize" value="100000"/>
</bean>
當(dāng)然為了使multipart解析器能夠工作,必須把合適的jar放到類路徑里。對(duì)于
CommonsMultipartResolver
來(lái)說(shuō),需要
commons-fileupload.jar
。注意,必須使用至少1.1
版本的Commons FileUpload,因?yàn)橐郧暗陌姹静恢С諮SR-168應(yīng)用。
現(xiàn)在你已經(jīng)看到如何設(shè)置Portlet MVC來(lái)處理multipart請(qǐng)求,接下來(lái)我們
討論它的使用。當(dāng)DispatcherPortlet
檢測(cè)到
multipart時(shí),它會(huì)激活在context里聲明的解析器,并把請(qǐng)求交給它。然后解析器
把當(dāng)前的ActionRequest
放到支持文件上傳的
MultipartActionRequest
中。通過(guò)
MultipartActionRequest
,可以得到
請(qǐng)求包含的multipart信息,并且在控制器里訪問(wèn)multipart文件。
注意,不能從RenderRequest
接收到multipart
文件,而只能從ActionRequest
里。
在 PortletMultipartResolver
處理完后,
請(qǐng)求會(huì)繼續(xù)被處理。你需要?jiǎng)?chuàng)建一個(gè)帶有上傳字段的表單來(lái)使用它(見(jiàn)下面),Spring會(huì)
把文件綁定在你的表單上(支持對(duì)象)。為了讓用戶上傳文件,必須創(chuàng)建一個(gè)(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>
如你所見(jiàn),我們?cè)赽ean的屬性后面創(chuàng)建名為“File”的字段
用來(lái)容納 byte[]
。加上了編碼屬性( enctype="multipart/form-data"
),
讓瀏覽器知道怎樣來(lái)編碼multipart字段(切記?。?/p>
和其它那些不會(huì)自動(dòng)轉(zhuǎn)化為字符串或原始類型的屬性一樣,為了把二進(jìn)制數(shù)據(jù)放到對(duì)象
里,必須注冊(cè)一個(gè)使用 PortletRequestDataBinder
的自定義的編輯器?,F(xiàn)成有好幾個(gè)編輯器可以用來(lái)處理文件并把結(jié)果放到對(duì)象上。
StringMultipartFileEditor
能夠把文件轉(zhuǎn)換成字符串
(使用用戶定義的字符集),ByteArrayMultipartFileEditor
能夠把文件轉(zhuǎn)換成字節(jié)數(shù)據(jù)。他們的功能和
CustomDateEditor
一樣。
所以,為了能夠使用表單來(lái)上傳文件,需要聲明解析器,映射到處理這個(gè)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í)際容納這個(gè)文件屬性的類。
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; } }
如你所見(jiàn),FileUploadBean
有一個(gè)類型是
byte[]
的屬性來(lái)容納文件??刂破髯?cè)了一個(gè)自定義編輯器來(lái)
讓Spring知道如何把解析器發(fā)現(xiàn)的multipart轉(zhuǎn)換成指定的屬性。在這個(gè)例子里,
沒(méi)有對(duì)bean的 byte[]
屬性進(jìn)行任何操作,但實(shí)際上,你可以做任
何操作(把它存到數(shù)據(jù)庫(kù)里,把它電郵出去,或其它)
下面是一個(gè)例子,文件直接綁定在的一個(gè)(表單支持)對(duì)象上的字符串類型屬性上面:
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)然,最后的例子在上傳文本文件時(shí)才有(邏輯上的)意義(在上傳圖像文件時(shí),它不會(huì)工作)。
第三個(gè)(也是最后一個(gè))選項(xiàng)是,什么情況下需要直接綁定在(表單支持)對(duì)象的
MultipartFile
屬性上。在以下的情況,不需要注冊(cè)自定義的屬性編輯器,因?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; } }