(十五)struts2的文件上传和下载

文件上传的原理

我们以前学习上传的时候知道需要将表单的enctype属性设置为multipart/form-data. 表单的enctype属性指定的是表单数据的编码方式,有三个值: -application/x-www-form-urlencoded:这是默认的编码方式。只处理表单的value属性值。采用这种会将表单域的值处理为url编码方式。 -multipart/form-data:这种编码方式会以二进制流的方式来处理表单数据,会将文件域里指定文件内容也封装到请求参数里。 -text/plain:这种方式主要用于直接通过表单发送邮件的情况。

 

我们用一个简单的案例来说明一下application/x-www-form-urlencoded 和multipart/form-data的区别。

案例:上传表单

1
2
3
4
5
6
7
<body>
    <form action="${pageContext.request.contextPath }/DemoServlet" enctype="application/x-www-form-urlencoded" method="post">
        上传文件:<input type="file" name="file"><br>
        请求参数:<input type="text" name="username"><br>
        <input type="submit" value="提交" name="dd"
    </form>
</body>

处理Servlet,这里的处理直接通过二进制流来处理http请求。这是底层的方式,当通过request的getParameter方法获取请求参数时,实际上是web服务器替我们处理了这种底层的二进制流,并转换成对应的请求参数值。

1
2
3
4
5
6
7
8
9
10
11
12
13
public class DemoServlet extends HttpServlet {
 
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        InputStream is=request.getInputStream();
        BufferedReader br=new BufferedReader(new InputStreamReader(is));
        String buffer=null;
        while((buffer=br.readLine())!=null)
        {
            System.out.println(buffer);
        }
    }
 
}
1
2
3
4
5
6
7
8
9
然后我们访问页面,选中file.txt文件 输入框中输入张三 ,点击提交
            输出
            file=file.txt&username=%E5%BC%A0%E4%B8%89&dd=%E6%8F%90%E4%BA%A4
 
            这个字符串包含了三个属性,file,username 和 dd
            浏览器会将表单里所有具有name属性的表单项转换成请求参数,因为提交按钮也有name属性,因此也被转换成请求参数。
 
            这里的编码都是使用url编码。可以通过java提供的URLDecoder解码。
            大部分时候,程序中通过getParameter方法即可获得参数,底层的二进制流处理,以及使用URLDecoder处理请求参数,都由web服务器帮我们完成了,。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
显然,通过上面这种方式,只能获取到文件名,不能获取到文件的内容,所以为了实现文件上传,只能将enctype属性设置为multipart/form-data.
                一旦设置了表单的 enctype属性设置为multipart/form-data  getParameter方法就无法使用。
 
 
                当我们设置完以后,再次点击提交,则输出
 
                        ------WebKitFormBoundary2lDSbdeEx3KW1Tup
                        Content-Disposition: form-data; name="file"; filename="file.txt"
                        Content-Type: text/plain
 
                        我是上传文件
                        ------WebKitFormBoundary2lDSbdeEx3KW1Tup
                        Content-Disposition: form-data; name="username"
 
                        zhangsan
                        ------WebKitFormBoundary2lDSbdeEx3KW1Tup--
 
                这时我们发现文件的内容也获取到,我们只需要通过io流的知识将其分割然后获取指定的参数即可。
                对于一个成熟的文件上传框架,需要完成的逻辑很简单,分析request请求的二进制流,解析出数据,然后允许开发者以简单的方式获取数据内容即可。
 
                Servlet3.0给我们所提供了提供了更加简单的文件上传方法,我们可以查阅API进行使用,这里不再细说。

 

 

Struts2的文件上传

struts2并未提供自己的上传组件。在struts.properties配置文件中,可以看到底层配置的是Common-fileupload组件。

但struts在原有的组件上进行了封装,因此底层的上传组件可以随意切换,代码不用变化

(1)编写我们的Action动作类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
public class UploadAction extends ActionSupport {
    private String username;
    private File upload; //封装了文件内容,无法获得文件名和文件类型
    private String uploadContentType;//封装了文件类型,xxxContentType
    private String uploadFileName; //用xxxFileName封装文件名字
 
    public String getUsername() {
        return username;
    }
 
    public void setUsername(String username) {
        this.username = username;
    }
 
    public File getUpload() {
        return upload;
    }
 
    public void setUpload(File upload) {
        this.upload = upload;
    }
 
    public String getUploadContentType() {
        return uploadContentType;
    }
 
    public void setUploadContentType(String uploadContentType) {
        this.uploadContentType = uploadContentType;
    }
 
    public String getUploadFileName() {
        return uploadFileName;
    }
 
    public void setUploadFileName(String uploadFileName) {
        this.uploadFileName = uploadFileName;
    }
 
    public String upload(){ 
        //获取真实路径
        String savepath=ServletActionContext.getRequest().getRealPath("/WEB-INF/files");
        File file=new File(savepath);
        //判断文件是否存在,不存在就创建相应的目录等
        if(!file.exists()){
            file.mkdirs();
        }
        //将上传的临时文件重命名并且另存到指定地址
        upload.renameTo(new File(file,uploadFileName));
        return null;
    }
 
}

 (2)配置Action

1
2
3
4
<package name="p1" extends="struts-default">
    <action name="upload" class="com.cad.struts2.action.UploadAction" method="upload">
    </action>
</package>

 

 

文件过滤

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
我们可以自己手动判断文件大小,文件类型来进行文件过滤,但是比较繁琐。
struts2为我们提供了一个fileUpload拦截器,来帮我们实现文件过滤。
fileUpload拦截器也被配置在了默认的拦截器栈中
 
fileUpload拦截器有两个参数
-allowedTypes:该参数指定允许上传的文件类型,多个文件类型之间用逗号分割,
-maximumSize:该属性指定允许上传的文件大小,单位是字节
struts2默认的允许上传文件大小为2MB。
 
设置最大允许上传文件大小为30M ,经过测试,这种方法行不通,不知道具体原因是什么。
<action name="upload" class="com.cad.struts2.action.UploadAction" method="upload">
    <interceptor-ref name="defaultStack">
        <param name="fileUpload.allowedTypes">image/jpg</param>
        <param name="fileUpload.maximumSize">31457280</param>
    </interceptor-ref>
</action>
 
所以我们只能通过配置常量来修改允许上传文件的大小
<constant name="struts.multipart.maxSize" value="31457280"></constant>

  

同时上传多个文件

1
2
3
4
5
6
7
8
9
10
11
12
需要将文件表单项的name设置成相同的。
 
    表单页面
        <body>
                <form action="${pageContext.request.contextPath }/upload.action" enctype="multipart/form-data" method="post">
                上传文件1:<input type="file" name="upload"><br>
                上传文件2:<input type="file" name="upload"><br>
                上传文件3:<input type="file" name="upload"><br>
                用户名:<input type="text" name="username"><br>
                <input type="submit" value="提交">   
            </form>
        </body>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
然后写Action类,需要将file,fileName,ContentType等用数组封装起来
然后遍历得到
public class UploadAction extends ActionSupport {
    private String username;
    private File upload[];
    private String uploadContentType[];
    private String uploadFileName[];
 
    public String getUsername() {
        return username;
    }
 
    public void setUsername(String username) {
        this.username = username;
    }
 
 
    public File[] getUpload() {
        return upload;
    }
 
    public void setUpload(File[] upload) {
        this.upload = upload;
    }
 
    public String[] getUploadContentType() {
        return uploadContentType;
    }
 
    public void setUploadContentType(String[] uploadContentType) {
        this.uploadContentType = uploadContentType;
    }
 
    public String[] getUploadFileName() {
        return uploadFileName;
    }
 
    public void setUploadFileName(String[] uploadFileName) {
        this.uploadFileName = uploadFileName;
    }
 
    public String upload(){
        String savepath=ServletActionContext.getRequest().getRealPath("/WEB-INF/files");
        File file=new File(savepath);
        if(!file.exists()){
            file.mkdirs();
        }
        for(int i=0;i<upload.length;i++){
            upload[i].renameTo(new File(file,uploadFileName[i]));
        }
        return null;
    }
 
}

 

Struts2的文件下载

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
创建下载的action类
 
            public class DownloadAction extends ActionSupport {
                private InputStream input;
 
                public InputStream getInput() {
                    return input;
                }
 
                public void setInput(InputStream input) {
                    this.input = input;
                }
 
                public String download() throws Exception{
                    //获取文件路径
                    String path=ServletActionContext.getRequest().getRealPath("/WEB-INF/files/photo.jpg");
                    //读取文件
                    input=new FileInputStream(path);
                    return SUCCESS;
                }
            }

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
配置Action
            struts2指定了stream结果类型,专门用来处理下载。
 
            contentType:被下载文件的文件类型。
            contentDisposition:下载文件弹窗,文件名等
            inputName:action类中流的名字
 
            <action name="download" class="com.cad.struts2.action.DownloadAction" method="download">
                <result name="success" type="stream">
                    <param name="contentType">application/octet-stream</param>
                    <param name="contentDisposition">attachment;filename=phpto.jpg</param>
                    <param name="inputName">input</param>
                </result>
            </action>

  

 

 

 

  

  

 

  

  

  

  

posted @   跃小云  阅读(199)  评论(0编辑  收藏  举报
努力加载评论中...
点击右上角即可分享
微信分享提示