Strust2第(十三)篇《实现文件上传和下载 》

本文来自:曹胜欢博客专栏。转载请注明出处:http://blog.csdn.net/csh624366188

文件上传和文件下载是我们在web应用程序中常用的两个功能,在java中,实现这两种功能的方式也有很多种,其中struts2就给我们提供了一种算是比较简单的方式吧,下面我们就一起来看一下,首先我们来看文件上传:


 文件上传

         文件上传我们首先应该注意的是在上传页面的表单,这个表单也是有讲究的,由于我们提交表单的数据中有文件上传,所以这个表单的所使用的编码类型就不能是原来的了,在这里我们应该使用的编码方式是multipart/form-data并且数据提交方式要用post方式,下面我们具体来看一下:

Form.jsp

  1. <form action="StudentAction!addStu" target="mainFrame" onsubmit="javascript:window.close()" method="post"   
  2. enctype="multipart/form-data">  
  3. <table class="ta" width="200px">  
  4. <td>姓名</td>  
  5. <td><input type="text" name="stu.name" value="${request.stu_info.name }"/></td>  
  6. </tr>  
  7. <tr bgColor="#6fdd0">  
  8. <td>上传头像</td>  
  9. <td><input type="file" name="file" />  
  10.          </td>  
  11. </tr>  
  12. <tr bgColor="#6fdd0">  
  13. <td colspan="2"><input type="submit"  value="提交" class="buStyle"/>     <input type="reset"  value="重置" class="buStyle"/></td>  
  14. </tr>  
  15. </table>  
  16. </form>  
<form action="StudentAction!addStu" target="mainFrame" οnsubmit="javascript:window.close()" method="post" 
enctype="multipart/form-data">
<table class="ta" width="200px">
<td>姓名</td>
<td><input type="text" name="stu.name" value="${request.stu_info.name }"/></td>
</tr>
<tr bgColor="#6fdd0">
<td>上传头像</td>
<td><input type="file" name="file" />
      	 </td>
</tr>
<tr bgColor="#6fdd0">
<td colspan="2"><input type="submit"  value="提交" class="buStyle"/>     <input type="reset"  value="重置" class="buStyle"/></td>
</tr>
</table>
</form>

     OK,看完表单以后我们就要来看一下action里面是怎么来接收这些数据的,其实也很简单,直接在action中定义三个变量,这三个变量分别是文件、文件名,还有文件类型,如下:

  1. private File file;  
  2. private String fileFileName;  
  3. private String fileContentType;  
private File file;
private String fileFileName;
private String fileContentType;

        这三个变量的名字是有讲究的,不是随便命名就OK了,其中file这个变量名要和表单中文件的name要相同,fileFileName这个也是固定的,起名格式就是name+FileName,同样fileContentType也是如此,命名规则是name+ContentType,只有你按照命名规则来定义变量,struts2才能把文件上传相关信息收集起来。Ok,看完了变量设置,下面我们来看一下怎么struts2是怎么把文件上传到我们指定的位置的。那我们就先上代码,让代码帮我们来理解:

  1. String root = ServletActionContext.getRequest().getRealPath("/upload");  
  2. try{  
  3. InputStream is = new FileInputStream(file);  
  4. // 创建一个文件,路径为root,文件名叫fileFileName   
  5. //自定义文件名    fileFileName="111"+fileFileName.substring(fileFileName.lastIndexOf("."));   
  6. File destFile = new File(root, fileFileName);  
  7. // 开始上传   
  8. OutputStream os = new FileOutputStream(destFile);  
  9. byte[] buffer = new byte[50000];  
  10. int length = 0;  
  11. // enctype="multipart/form-data"   
  12. while (-1 != (length = is.read(buffer))) {  
  13. os.write(buffer, 0, length);  
  14. }  
String root = ServletActionContext.getRequest().getRealPath("/upload");
try{
InputStream is = new FileInputStream(file);
// 创建一个文件,路径为root,文件名叫fileFileName
//自定义文件名	fileFileName="111"+fileFileName.substring(fileFileName.lastIndexOf("."));
File destFile = new File(root, fileFileName);
// 开始上传
OutputStream os = new FileOutputStream(destFile);
byte[] buffer = new byte[50000];
int length = 0;
// enctype="multipart/form-data"
while (-1 != (length = is.read(buffer))) {
os.write(buffer, 0, length);
}

      我们可以看到,就是简单的几行代码,其实并不难,他主要就是利用了IO流来实现的文件上传。单文件上传实现以后,多文件上传实现起来就不难了。


多文件上传

与单文件上传相似,Struts 2实现多文件上传也很简单。你可以使用多个<s:file />绑定Action的数组或列表。

  1. < s:form action ="doMultipleUploadUsingList" method ="POST" enctype ="multipart/form-data" >   
  2.     < s:file label ="File (1)" name ="upload" />   
  3.     < s:file label ="File (2)" name ="upload" />   
  4.     < s:file label ="FIle (3)" name ="upload" />   
  5.     < s:submit />   
  6. </ s:form >  
< s:form action ="doMultipleUploadUsingList" method ="POST" enctype ="multipart/form-data" > 
    < s:file label ="File (1)" name ="upload" /> 
    < s:file label ="File (2)" name ="upload" /> 
    < s:file label ="FIle (3)" name ="upload" /> 
    < s:submit /> 
</ s:form >


如果你希望绑定到数组,Action的代码应类似:

   

  1. private File[] uploads;  
  2.    private String[] uploadFileNames;  
  3.    private String[] uploadContentTypes;  
  4.   
  5.    public File[] getUpload() { return this .uploads; }   
  6.    public void setUpload(File[] upload) { this .uploads = upload; }   
  7.   
  8.    public String[] getUploadFileName() { return this .uploadFileNames; }   
  9.    public void setUploadFileName(String[] uploadFileName) { this .uploadFileNames = uploadFileName; }   
  10.   
  11.    public String[] getUploadContentType() { return this .uploadContentTypes; }   
  12.    public void setUploadContentType(String[] uploadContentType) { this .uploadContentTypes = uploadContentType; }  
  private File[] uploads;
     private String[] uploadFileNames;
     private String[] uploadContentTypes;

     public File[] getUpload() { return this .uploads; } 
     public void setUpload(File[] upload) { this .uploads = upload; } 
 
     public String[] getUploadFileName() { return this .uploadFileNames; } 
     public void setUploadFileName(String[] uploadFileName) { this .uploadFileNames = uploadFileName; } 
 
     public String[] getUploadContentType() { return this .uploadContentTypes; } 
     public void setUploadContentType(String[] uploadContentType) { this .uploadContentTypes = uploadContentType; }

如果你想绑定到列表,则应类似:


     

  1. private List < File > uploads = new ArrayList < File > ();  
  2.      private List < String > uploadFileNames = new ArrayList < String > ();  
  3.      private List < String > uploadContentTypes = new ArrayList < String > ();  
  4.   
  5.      public List < File > getUpload() {  
  6.          return this .uploads;  
  7.     }   
  8.      public void setUpload(List < File > uploads) {  
  9.          this .uploads = uploads;  
  10.     }   
  11.    
  12.      public List < String > getUploadFileName() {  
  13.          return this .uploadFileNames;  
  14.     }   
  15.      public void setUploadFileName(List < String > uploadFileNames) {  
  16.          this .uploadFileNames = uploadFileNames;  
  17.     }   
  18.    
  19.      public List < String > getUploadContentType() {  
  20.          return this .uploadContentTypes;  
  21.     }   
  22.      public void setUploadContentType(List < String > contentTypes) {  
  23.          this .uploadContentTypes = contentTypes;  
  24.     }  
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;
    }

    收集好数据之后,文件上传步骤就和上面单文件的一样了。在这就不重复了。好了,文件上传占时先说到这,下一步我们来看一下文件下载。

文件下载

          Struts 2中对文件下载做了直接的支持,相比起自己辛辛苦苦的设置种种HTTP头来说,现在实现文件下载无疑要简便的多。说起文件下载,最直接的方式恐怕是直接写一个超链接,让地址等于被下载的文件,例如:<a href=file1.zip> 下载file1.zip</a> ,之后用户在浏览器里面点击这个链接,就可以进行下载了。但是它有一些缺陷,例如如果地址是一个图片,那么浏览器会直接打开它,而不是显示保存文件的对话框。再比如如果文件名是中文的,它会显示一堆URL编码过的文件名例如%3457...。而假设你企图这样下载文件:http://localhost:8080/struts2/download/java程序员由笨鸟到菜鸟.doc ,Tomcat会告诉你一个文件找不到的404错误:HTTP Status 404 - /struts2hello/download/ϵͳ˵Ã÷.doc 。 所以在此我们就要用到struts 给我们提供的文件下载了。下面我们就一起来看一下struts2给我们提供的文件下载:

其实struts2提供给我们的文件下载已经非常简单化了,编写一个普通的Action就可以了,只需要提供一个返回InputStream流的方法,该输入流代表了被下载文件的入口,这个方法用来给被下载的数据提供输入流,意思是从这个流读出来,再写到浏览器那边供下载。这个方法需要由开发人员自己来编写,只需要返回值为InputStream即可 。首先我们来看一下jsp页面:

  1. <body>    
  2.    <h1>文件下载</h1>    
  3.    <!-- 下载链接 -->    
  4.    <s:a action="down.action">download</s:a>    
  5.  </body>    
 <body>  
    <h1>文件下载</h1>  
    <!-- 下载链接 -->  
    <s:a action="down.action">download</s:a>  
  </body>  


页面很简单,就一下下载的链接,然后这个链接链接到我们的action中,下一步我们来看一下我们的action的编写:

  1. public class DownAction extends ActionSupport {  
  2.      private static final long serialVersionUID = 1L;  
  3.     private String inputPath;  
  4.     public String getInputPath() {  
  5.         return inputPath;  
  6.     }  
  7.     public void setInputPath(String inputPath) {  
  8.         this.inputPath = inputPath;  
  9.     }  
  10.     /* 
  11.      * 下载用的Action应该返回一个InputStream实例,该方法对应在result里的inputName属性为 
  12.      * getDownloadFile 
  13.      */  
  14.     public InputStream getDownloadFile()  
  15.     {  
  16.         return ServletActionContext.getServletContext().getResourceAsStream(  
  17.         "/upload/Struts2.txt");  
  18.     }  
  19.     public String execute() throws Exception  
  20.     {  
public class DownAction extends ActionSupport {
     private static final long serialVersionUID = 1L;
    private String inputPath;
    public String getInputPath() {
        return inputPath;
    }
    public void setInputPath(String inputPath) {
        this.inputPath = inputPath;
    }
    /*
     * 下载用的Action应该返回一个InputStream实例,该方法对应在result里的inputName属性为
     * getDownloadFile
     */
    public InputStream getDownloadFile()
    {
        return ServletActionContext.getServletContext().getResourceAsStream(
        "/upload/Struts2.txt");
    }
    public String execute() throws Exception
    {
  1. return SUCCESS;  
return SUCCESS;
  1. }  
}
  1. }  
}


下面我们在来看一下struts.xml的配置:

       

  1. <action name="down" class="cn.csdn.hr.up.action.DownAction">  
  2.            <!-- 配置结果类型为stream的结果 -->  
  3.            <result name="success" type="stream">  
  4.                <!-- 指定被下载文件的文件类型 -->  
  5.                <param name="contentType">text/plain </param>  
  6.                <!-- 指定下载文件的文件位置 -->  
  7.                <param name="contentDisposition">attachment;filename="Struts2.txt"</param>  
  8.                <param name="inputName">downloadFile</param>  
  9.            </result>  
  10.        </action>  
 <action name="down" class="cn.csdn.hr.up.action.DownAction">
            <!-- 配置结果类型为stream的结果 -->
            <result name="success" type="stream">
                <!-- 指定被下载文件的文件类型 -->
                <param name="contentType">text/plain </param>
                <!-- 指定下载文件的文件位置 -->
                <param name="contentDisposition">attachment;filename="Struts2.txt"</param>
                <param name="inputName">downloadFile</param>
            </result>
        </action>

这个action特殊的地方在于result的类型是一个流(stream ),配置stream类型的结果时,因为无需指定实际的显示的物理资源,所以无需指定location 属性,只需要指定inputName 属性,该属性指向被下载文件的来源,对应着Action类中的某个属性,类型为InputStream。下面则列出了和下载有关的一些参数列表:

参数说明

contentType

内容类型,和互联网MIME标准中的规定类型一致,例如text/plain代表纯文本,text/xml表示XMLimage/gif代表GIF图片,image/jpeg代表JPG图片

inputName

下载文件的来源流,对应着action类中某个类型为Inputstream的属性名,例如取值为inputStream 的属性需要编写getInputStream()方法

contentDisposition

文件下载的处理方式,包括内联(inline)和附件(attachment)两种方式,而附件方式会弹出文件保存对话框,否则浏览器会尝试直接显示文件。取值为:attachment;filename="struts2.txt" ,表示文件下载的时候保存的名字应为struts2.txt 。如果直接写filename="struts2.txt" ,那么默认情况是代表inline ,浏览器会尝试自动打开它,等价于这样的写法:inline; filename="struts2.txt"

bufferSize

下载缓冲区的大小

在这里面,contentType 属性和contentDisposition 分别对应着HTTP响应中的头Content-Type 和Content-disposition 头


当然,在很多的时候我们一般都不是把文件名写死在xml配置当中的,我们一般会在action中定义一个变量downfilename,储存这个文件名,然后再xml配置:

  1. <param name="contentDisposition">attachment;filename="${downloadFileName}"</param>  
 <param name="contentDisposition">attachment;filename="${downloadFileName}"</param>

我们经常在中文下载中,出现文件名乱码的问题,这个问题是很多人都常见的,具体的很好的解决方法也没有,但我以前用的时候尝试着给他重新编码,这样可以解决大部分时候的中文下载乱码问题,但有时候也不行的。具体重新编码就是:

  1. downFileName = new String(downFileName.getBytes(), "ISO8859-1");      
downFileName = new String(downFileName.getBytes(), "ISO8859-1");    

    好了,struts2文件上传和下载就简单介绍到这,文章中有什么不对或者错误的地方,欢迎大家指正。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值