Webx系列之文件上传

来源:互联网 发布:gre gmat 知乎 编辑:程序博客网 时间:2024/06/04 01:24

做过文件上传功能开发的人员都知道,对于文件上传需要设置表单类型 enctype="multipart/form-data"(Content Type为multipart/form-data)。后台获取form data需要根据form类型(fileItem.isFormField())去判断是否是文件类型,如果再有其他参数数据的话,获取参数就会非常麻烦。而Webx提供了一个很好的接口(ParserRequestContext),帮助我们实现文件上传和获取普通参数。而这个接口的实现依赖于<parser> - 解析参数和Upload,我们来看下官方文档对于<parser> - 解析参数和Upload服务的介绍:

基本配置

首先我们需要在Webx.xml里进行这样的配置:
<services:request-contexts xmlns="http://www.alibaba.com/schema/services/request-contexts"><parser />...</services:request-contexts><services:upload sizeMax="5M" fileSizeMax="2M" />
绝大多数情况下,你只需要上面的配置就足够了 ── <parser>会自动解析所有类型的请求,包括:
  1. GET请求
  2. 普通的POST请求(Content Type:application/x-www-form-urlencoded)
  3. 可上传文件的POST请求(Content Type:multipart/form-data)

访问参数

访问参数的时候,你有两种选择:

  1. 通过HttpServletRequest接口访问参数 
  2. 通过ParserRequestContext接口访问参数

HttpServletRequest接口访问参数 

我们先说一下HttpServletRequest接口访问参数:

写法如下:

@AutowiredHttpServletRequest request;...String s = request.getParameter("myparam");

你只需要在你的Action处理类通过@Autowired注解注入就OK了,然后你可以像你习惯的获取参数的方式进行参数值的获取,不过你需要注意的是:你只是看来感觉和你之前用的HttpServletRequest没什么区别,其实它是经过Webx封装过的实现类,你需要特别注意的是:你没有办法像之前那样获取文件表单数据,因为它已经不支持了,其他的正常。如果你想获取文件表单数据怎么办呢?很简单,用ParserRequestContext。

ParserRequestContext访问参数

写法如下:

@AutowiredParserRequestContext parser;...String s = parser.getParameters().getString("myparam");
ParRequestContext是一个比HttpServletRequest接口要方便非常非常的多的一个接口,至于方便在哪里,我们接下来说明:

        1、 直接取得指定类型的参数,例如:直接取得int、boolean值等。

// myparam=true, myparam=falseparser.getParameters().getBoolean("myparam");// myparam=123parser.getParameters().getInt("myparam");
2、如果参数值未提供,或者值为空,则返回指定默认值。

parser.getParameters().getBoolean("myparam", false);parser.getParameters().getString("myparam", "no_value");parser.getParameters().getInt("myparam", -1);
3、最为方便的莫过于文件上传,你可以直接获取FileItem。
FileItem fileItem = parser.getParameters().getFileItem("myfile");FileItem[] fileItems = parser.getParameters().getFileItems("myfile");
4、访问Cookie

parser.getCookies().getString("mycookie");
你需要注意的是:如果你的表单里既有普通的参数数据,又有文件上传的参数数据,你可以直接进行获取就行了,不用像之前那么麻烦的操作。下面问来看一个例子:

$page.setTitle("文件上传页面")<script type="text/javascript">    function doClick(){        document.getElementsByName("fileUploadName")[0].value = document.getElementsByName("fileUpload")[0].value    }</script><p>文件上传页面</p><form action="" method="post" enctype="multipart/form-data">    $csrfToken.hiddenField    #set($group = $form.testRegister.defaultInstance)    <input type="hidden" name="action" value="file_uploadAction"/>    <table>        <tr>            <td>姓名:</td>            <td><input type="text" id="userName" name="userName" value="$!userName" /></td>        </tr>        <tr>            <td>密码</td>            <td><input type="text" name="passWord" id="passWord" value="$!passWord"/></td>        </tr>        <tr>            <td>文件上传</td>            <td><input type="text" name="fileUploadName" value="$!fileUploadName" >                <input type="file" name="fileUpload" onchange="doClick()"/></td>        </tr>        <tr>        <td><input type="submit" value="提交" name="event_submit_do_upload"></td>        <td><input type="reset" value="重置"></td>        </tr>    </table></form>

package com.alibaba.webx.MyWebxTest.myWebX.module.action;import com.alibaba.citrus.service.requestcontext.parser.ParserRequestContext;import com.alibaba.citrus.turbine.Context;import com.alibaba.citrus.turbine.Navigator;import com.alibaba.citrus.turbine.dataresolver.Param;import org.apache.commons.fileupload.FileItem;import org.springframework.beans.factory.annotation.Autowired;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.File;/** * Created by zkn on 2016/4/7. */public class FileUploadAction {    @Autowired    private HttpServletRequest request;    @Autowired    private HttpServletResponse response;    /**     * Webx默认解析请求的类     */    @Autowired    private ParserRequestContext parserContext;    public void doUpload(@Param("userName") String name, Context context, Navigator na) {        //获取用户名        String userName = request.getParameter("userName");        //获取密码        String passWord = request.getParameter("passWord");        System.out.println("userName:"+userName+"   passWord:"+passWord);        //Webx实现文件上传        FileItem fileItem = parserContext.getParameters().getFileItem("fileUpload");        String fileDir = "D:\\Document";        try{            fileItem.write(new File(fileDir+"\\"+System.currentTimeMillis()+fileItem.getName()));        }catch (Exception e){            e.printStackTrace();        }    }}

看起来是不是很方便啊。

上面介绍完了<parser />解析参数,下面我们来介绍Upload服务,如果没有配置Upload服务,只是<parser />的话那么<parser>还是不可以解析multipart/form-data表单请求的。

Upload服务

配置Upload服务

Upload服务的配置参数如下:
<services:upload sizeMax="5M" fileSizeMax="2M" repository="/tmp" sizeThreshold="10K" keepFormFieldInMemory="true" />
Upload服务配置参数说明

参数名称说明sizeMaxHTTP请求的最大尺寸(字节,支持K/M/G),超过此尺寸的请求将被抛弃。值-1表示没有限制。fileSizeMax单个文件允许的最大尺寸(字节,支持K/M/G),超过此尺寸的文件将被抛弃。值-1表示没有限制。repository暂存上传文件的目录。 注意,这个目录是用SpringResourceLoader装载
的,而不是一个物理路径。关于ResourceLoader,详见ResourceLoading
服务的文档。sizeThreshold将文件放在内存中的阈值(字节,支持K/M/G),小于此值的文件被保存在
内存中keepFormFieldInMemory是否将普通的form field保持在内存里? 默认为false,但
当sizeThreshold为0时,默认为true

注意:

当上传文件的请求的总尺寸超过sizeMax的值时,整个请求将被抛弃 ——这意味着你不可能读到请求中的其它任何参数。而当某个上传文件的尺寸超出fileSizeMax的限制,

但请求的总尺寸仍然在sizeMax的范围内时,只有超出该尺寸的单个上传文件被抛弃,而你还是可以读到其余的参数。

手工解析上传请求

在默认情况下,当<parser>收到一个上传文件的请求时,会立即解析并取得所有的参数和文件。然而你可以延迟这个过程,在需要的时候,再手工解析上传请求。
首先:你需要关闭自动上传
<parser autoUpload="false">
然后:你只需要调用下面这句话就可以了
parser.getParameters().parseUpload();
手工调用parseUpload(),你可以指定和默认不同的参数:
UploadParameters params = new UploadParameters();params.applyDefaultValues();params.setSizeMax(new HumanReadableSize("10M"));params.setFileSizeMax(new HumanReadableSize("1M"));params.setRepository(new File("mydir"));parser.getParameters().parseUpload(params);

限制文件类型

在Webx里,你可以用一种简单的方式来进行文件类型的过滤(想当年在这里我可以被坑的不能行啊。。。),话不多说,配置如下:
<filters><parser-filters:uploaded-file-whitelistextensions="jpg, gif, png" /></filters>
对文件类型的过滤是用到了Webx里的UploadedFileFilte过滤器接口,其实,<parser>支持两种过滤器接口:ParameterValueFilter和UploadedFileFilter。前者用来对普通的参数值进行过滤(例如排除可能造成攻击的HTML代码);后者用来对上传文件的file item对象进行过滤,就像刚才的uploaded-file-whitelist的例子。
另外<parser> - 解析参数还有很多高级的用法,我们以后再说。



1 0
原创粉丝点击