码农小汪-struts2学习10-上传下载文件

来源:互联网 发布:手机淘宝我要开店 编辑:程序博客网 时间:2024/06/05 11:29

上传文件和下载文件,struts2为文件上传下载提供了实现机制,我们只要按照规则使用就可以了,不要当心我们不会做,码农最重要的一点学习,看各种文档就是家常便饭,要学会适应这样的生活。dayday–raise

  • The org.apache.struts2.interceptor.FileUploadInterceptor class is included as part of the defaultStack. As long as the required libraries are added to your project you will be able to take advantage of of the Struts 2 fileUpload capability. Configure an Action mapping for your Action class as you typically would.
    规则是怎么样的呢?按照规则使用就行了
    A form must be create with a form field of type file, < INPUT type=”file” name=”upload”>.
    < FORM action=”doUpload”enctype=”multipart/form-data” method=”post”>
    The standard procedure for adding these elements is by using the Struts 2 tag libraries as shown in the following example:
<s:form action="doUpload" method="post" enctype="multipart/form-data">    <s:file name="upload" label="File"/>    <s:submit/></s:form>

The fileUpload interceptor will use setter injection to insert the uploaded file and related data into your Action class. For a form field named upload you would provide the three setter methods shown in the following example:
fileUpload拦截器将使用setter注入将上传的文件和相关的数据插入到你的操作类。 表单字段命名上传你能提供下面的示例中所示的三个setter方法:`。让我们去操作文件的属性啊。

方法签名 描述 setX(File file) The file that contains the content of the uploaded file. This is a temporary file and file.getName() will not return the original name of the file临时的文件哦。不会返回原来的名字 setXContentType(String contentType) The mime type of the uploaded file setXFileName(String fileName) The actual file name of the uploaded file (not the HTML name)真实的文件名哦

-首先我们要清楚一点,这里的file并不是真正指代jsp上传过来的文件,当文件上传过来时,struts2首先会寻找struts.multipart.saveDir 我在讲属性的时候说过的,可以去看看完整的就在前面的文章中提到过的(这个是在default.properties里面有)这个name所指定的存放位置,我们可以新建一个struts.properties属性文件来指定这个临时文件存放位置,如果没有指定,那么文件会存放在tomcat的localhost\目录下,然后我们可以指定文件上传后的存放位置,通过输出流将其写到流里面就行了,这时我们就可以在文件夹里看到我们上传的文件了。

这个下面的属性的名字随便,但是必须有相应的方法和我们的拦截器设置属性的一一对应起来才可以的。可以自己去看看那个拦截器怎么实现的,
也是有
ActionContext ac = invocation.getInvocationContext();
HttpServletRequest request=(HttpServletRequest) ac.get(ServletActionContext.HTTP_REQUEST);
这些东西是必须的!

package com.example;   import java.io.File;   import com.opensymphony.xwork2.ActionSupport;   public class UploadAction extends ActionSupport {      private File file;//临时的文件不可以获得getName()不是原来的啦      private String contentType;      private String filename;//这里的filename才是      public void setUpload(File file) {         this.file = file;      }      public void setUploadContentType(String contentType) {         this.contentType = contentType;      }      public void setUploadFileName(String filename) {         this.filename = filename;      }      public String execute() {         //...         return SUCCESS;      } }

我们还有对放入缓存的文件进行处理是,这个就是输入输出的事情啦啦

 public String execute() throws Exception    {        String root =ServletActionContext.getServletContext().getRealPath("/upload");               InputStream is = new FileInputStream(file);        //输出到指定的文件就行了。        OutputStream os = new FileOutputStream(new File(root, fileFileName));        System.out.println("fileFileName: " + fileFileName);    // 因为file是存放在临时文件夹的文件,我们可以将其文件名和文件路径打印出来,看和之前的fileFileName是否相同        System.out.println("file: " + file.getName());        System.out.println("file: " + file.getPath());        byte[] buffer = new byte[500];        int length = 0;        while(-1 != (length = is.read(buffer, 0, buffer.length)))        {            os.write(buffer);        }        os.close();        is.close();        return SUCCESS;    }

Struts 2default.properties文件定义了几个设置影响行为的文件上传。 你可能会发现需要更改这些值。 名称和默认值是:

struts.multipart.parser=jakartastruts.multipart.saveDir=struts.multipart.maxSize=2097152

除了这个之外,我们还可以定义文件上传的类型,也可以不定义在xml中直接使用,我们的自己手动判断,也可以的。下面的拦截器是什么意思呢?自己可以看看的!百度…

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE struts PUBLIC     "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"     "http://struts.apache.org/dtds/struts-2.0.dtd"><struts>    <constant name="struts.multipart.maxSize" value="1000000" />    <action name="doUpload" class="com.example.UploadAction">        <interceptor-ref name="basicStack"/>        <interceptor-ref name="fileUpload">            <param name="maximumSize">500000</param>            //最大的文件大小            <param name="allowedTypes">image/jpeg,image/gif</param>            //文件的类型是什么        </interceptor-ref>         <interceptor-ref name="validation"/>        <interceptor-ref name="workflow"/>        <result name="success">good_result.jsp</result>    </action></struts>

发生错误,应为我们的拦截器在处理的时候,会把错误的key加入到我们的错误处理那里面的,我们可以通过key关键字获得错误类型,源码中可以看到发生错误哦,或增加进入的。

ValidationAware validation = null;        Object action = invocation.getAction();        if (action instanceof ValidationAware) {            validation = (ValidationAware) action;        }        MultiPartRequestWrapper multiWrapper = (MultiPartRequestWrapper) request;        if (multiWrapper.hasErrors()) {            for (String error : multiWrapper.getErrors()) {                if (validation != null) {                    validation.addActionError(error);                }            }        }
错误的关键 描述 struts.messages.error.uploading 一般的错误发生在文件无法上传 struts.messages.error.file.too.large 发生在maximumSize指定的上传文件太大。 struts.messages.error.content.type.not.allowed 上传文件时指定的预期内容类型不匹配 struts.messages.error.file.extension.not.allowed 上传文件时不允许扩展 struts.messages.upload.error.SizeLimitExceededException 发生在上传请求(作为一个整体)超过配置struts.multipart.maxSize struts.messages.upload.error。 <异常类SimpleName > 发生在任何其他文件上传过程中异常发生

download…

文件上传后我们还需要将其下载下来,其实struts2的文件下载原理很简单,就是定义一个输入流,然后将文件写到输入流里面就行,关键配置还是在struts.xml这个配置文件里配置

<result name="success" type="stream">  <param name="contentType">image/jpeg</param>  <param name="inputName">imageStream</param>  <param name="contentDisposition">attachment;filename="document.pdf"</param>  <param name="bufferSize">1024</param></result>
  • 结果类型必须要写成 type=”stream” ,与之对应的处理类是 org.apache.struts2.dispatcher.StreamResult.
    怎么处理的细节,那就太精妙了,好多细节,说不清楚,需要自己把整个流程很清楚才能看懂。我没看懂~
public class StreamResult extends StrutsResultSupport {    private static final long serialVersionUID = -1468409635999059850L;    protected static final Logger LOG = LoggerFactory.getLogger(StreamResult.class);    public static final String DEFAULT_PARAM = "inputName";    protected String contentType = "text/plain";    protected String contentLength;    protected String contentDisposition = "inline";    protected String contentCharSet ;    protected String inputName = "inputStream";    protected InputStream inputStream;    protected int bufferSize = 1024;    protected boolean allowCaching = true;
  • contentType - the stream mime-type as sent to the web browser (default = text/plain).
  • contentLength - the stream length in bytes (the browser displays a progress bar). 显示在浏览器上的长度
  • contentDisposition - the content disposition header value for specifing the file name (default = inline, values are typically attachment;filename=”document.pdf”.contentDisposition默认是 inline(内联的), 比如说下载的文件是文本类型的,就直接在网页上打开,不能直接打开的才会打开下载框自己选择, attachment :下载时会打开下载框,fileName=,该名字是显示在下载框上的文件名字
  • inputName - the name of the InputStream property from the chained action (default = inputStream) 这个是个代理,我们输出的流文件通过这个名字的get方法进行获取。下面有例子讲解的。
  • bufferSize - the size of the buffer to copy from input to output (default = 1024).
  • allowCaching if set to ‘false’ it will set the headers ‘Pragma’ and ‘Cache-Control’ to ‘no-cahce’, and prevent client from caching the content. (default = true)
  • contentCharSet if set to a string, ‘;charset=value’ will be added to the content-type header, where value is the string set. If set to an expression, the result of evaluating the expression will be used. If not set, then no charset will be set on the header
Annotation based Configuration,注解的方式package com.mycompany.webapp.actions;import java.io.File;import java.io.FileInputStream;import java.io.InputStream;import org.apache.struts2.convention.annotation.Result;import com.opensymphony.xwork2.Action;import com.opensymphony.xwork2.ActionSupport;@Result(    name = "success",     type = "stream",     params = {         "contentType", "${type}",         "inputName", "stream", //输入流的值在这里获取的!!!        "bufferSize", "1024",         "contentDisposition", "attachment;filename=\"${filename}\""     })public class FileDisplay extends ActionSupport {    private String type = "image/jpeg";    private String filename;    private InputStream stream;    public String execute() throws Exception {        filename = "myimage.jpg";        File img = new File("/path/to/image/image.jpg");        stream = new FileInputStream(img);        return Action.SUCCESS;    }    private String getType() {        return this.type;    }    private String getFilename() {        return this.filename;    }    private String getStream() {        return this.stream;    }}或者xml配置也可以!<result name="success" type="stream">  <param name="contentType">image/jpeg</param>  <param name="inputName">stream</param>//这个很重要的哦!!!和上面的一一对应啊!  <param name="contentDisposition">attachment;filename="document.pdf"</param>  <param name="bufferSize">1024</param></result>

我们的讲解,完了。我又去看小伙伴们的实现的!怎么样,加固我们的理解。

import com.opensymphony.xwork2.ActionSupport;//文件下载public class FileDownload extends ActionSupport{    private int number ;    private String fileName;    public int getNumber() {        return number;    }    public void setNumber(int number) {        this.number = number;    }    public String getFileName() {        return fileName;    }    public void setFileName(String fileName) {        this.fileName = fileName;    }    //返回一个输入流,作为一个客户端来说是一个输入流,但对于服务器端是一个 输出流!!!!注意这里,我们的inputname!!!==downloadFile  获得输出流!    public InputStream getDownloadFile() throws Exception    {        if(1 == number)        {           this.fileName = "Dream.jpg" ;           //获取资源路径           return ServletActionContext.getServletContext().getResourceAsStream("upload/Dream.jpg") ;        }        else if(2 == number)        {            this.fileName = "jd2chm源码生成chm格式文档.rar" ;            //解解乱码            this.fileName = new String(this.fileName.getBytes("GBK"),"ISO-8859-1");            return ServletActionContext.getServletContext().getResourceAsStream("upload/jd2chm源码生成chm格式文档.rar") ;        }        else           return null ;    }    @Override    public String execute() throws Exception {        return SUCCESS;    }}struts>         <package name="struts2" extends="struts-default">             <action name="FileDownload" class="com.struts2.filedownload.FileDownload">           <result name="success" type="stream">               <param name="contentType">text/plain</param>               <param name="contentDisposition">attachment;fileName="${fileName}"</param>               <param name="inputName">downloadFile</param>               <param name="bufferSize">1024</param>           </result>       </action>   </package></struts>

多文件的处理上传!一样的,贴哈代码自己体会

package org.apache.struts2.showcase.fileupload;import com.opensymphony.xwork2.ActionSupport;import java.io.File;import java.util.ArrayList;import java.util.List;/** * Showcase action - multiple file upload using List * * @version $Date$ $Id$ */public class MultipleFileUploadUsingListAction extends ActionSupport {    private List<File> uploads = new ArrayList<File>();    private List<String> uploadFileNames = new ArrayList<String>();    private List<String> uploadContentTypes = new ArrayList<String>();    public List<File> getUpload() {        return this.uploads;    }    public void setUpload(List<File> uploads) {        this.uploads = uploads;    }    public List<String> getUploadFileName() {        return this.uploadFileNames;    }    public void setUploadFileName(List<String> uploadFileNames) {        this.uploadFileNames = uploadFileNames;    }    public List<String> getUploadContentType() {        return this.uploadContentTypes;    }    public void setUploadContentType(List<String> contentTypes) {        this.uploadContentTypes = contentTypes;    }    public String upload() throws Exception {        System.out.println("\n\n upload1");        System.out.println("files:");        for (File u : uploads) {            System.out.println("*** " + u + "\t" + u.length());        }        System.out.println("filenames:");        for (String n : uploadFileNames) {            System.out.println("*** " + n);        }        System.out.println("content types:");        for (String c : uploadContentTypes) {            System.out.println("*** " + c);        }        System.out.println("\n\n");        return SUCCESS;    }}

…….搞定?哈哈!自己处理流的问题就好了,其他的都是上面一样的!
每天都有进步。

1 0
原创粉丝点击