文件上传和下载
 
一些需要注意的地方:
 
在处理到文件上传和下载的时候首先说明一些需要注意的地方。
 
1)  使用HTML默认的功能不能上传目录,这里的默认功能指的是不做额外的开发(例如ActiveX)的情况下。
   所以客户如果跟你说:“我有一个目录需要上传,能不能让我选择目录,然后一下子上传整个目录?”,出于工作量的考虑你最好回绝他,然后使用动态增加的方式来动态的支持多个上传文件,或者更简单的让客户指定所有的上传文件。
 
2)  不能设置文件上传字段的默认值。
   出于安全的考虑,HTML不支持默认的文件上传字段的默认值。例如,在你不知道的情况下,你访问了某个网站的某个页面,结果你的password文件被上传上去了,哈哈,你有危险了。
   所以如果客户跟你说:“我能不能打开画面的时候就设置好上传的文件?”,处于工作量和技术难度的考虑,你最好说:“哦,为了您的安全,还是不要这样子做了”,呵呵,
 
3)文件类型
    每一种文件都有类型,一般情况下扩展明决定了文件的类型。。所有文件类型的列表可以从这个目录中找到,相信可以为你提供参考:
TOMCAT_HOME\conf\web.xml  
<mime-mapping>
        <extension>bin</extension>
        <mime-type>application/octet-stream</mime-type>
</mime-mapping>
<mime-mapping>
        <extension>gif</extension>
        <mime-type>image/gif</mime-type>
</mime-mapping>
4) 下载文件时本页面内部打开,还是弹出另存对话框?
文件下载的时候可以在本页面打开,和可以弹出另存对话框。选择条件是设置文件下载的:contentDisposition,inline表示当前页面打开,attachment表示弹出另存对话框。
例如:
contentDisposition=inline;filename="image.jpg"             当前画面打开
contentDisposition=attachment;filename="image.jpg"         打开另存对话框
 
5)文件上传需要使用method="post" 和 enctype="multipart/form-data"类型的form
 
使用Struts2上传文件:
Struts文件上传需要使用File Upload Filter。Filter Upload Filter使用一些默认的规则:
Form中的<s:file name="image"></s:file>标签对应着Action类中的三个属性分别是:上传文件(java.io.File类 型),文件名(java.lang.String类型),文件类型(java.lang.String类型,例如:image/jpeg)。命名规约为:
文件:名字与<s:file>标签中的name属性一致,这里为:image
文件名:文件 + FileName,这里为:imageFileName
文件类型:文件 + ContentType,这里为:imageContentType
 
所以针对上述<s:file name="image"></s:file>表示啊的上传文件的JSP和Action类被别为:
 
imageUpload.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="s" uri="/struts-tags" %>
 
<html>
<head><title>Image Upload</title></head>
<body>
    <h1> Image Upload Page </h1>
 
    <s:form action="imageUpload" method="post" enctype="multipart/form-data">
        <s:file name="image"></s:file>
        <s:submit></s:submit>
 
    </s:form>
</body>
</html>
 
ImageUploadAction.java:
package com.jpleasure;
 
import com.opensymphony.xwork2.ActionSupport;
 
import java.io.File;
import java.io.InputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
 
public class ImageUploadAction extends ActionSupport {
 
    private File image;
    private String imageFileName;
    private String imageContentType;
 
    public File getImage() {
        return image;
    }
 
    public void setImage(File image) {
        this.image = image;
    }
 
    public String getImageFileName() {
        return imageFileName;
    }
 
    public void setImageFileName(String imageFileName) {
        this.imageFileName = imageFileName;
    }
 
    public String getImageContentType() {
        return imageContentType;
    }
 
    public void setImageContentType(String imageContentType) {
        this.imageContentType = imageContentType;
    }
 
 
    public String execute() {
 
        if (image != null) {
            System.out.println("file name is:" + this.imageFileName);
            System.out.println("file content type is:" + this.imageContentType);
            System.out.println("file length is:" + this.image.length());
         }
        return SUCCESS;
    }
}
 
Struts.xml配置文件:
<action name="imageUpload" class="com.jpleasure.ImageUploadAction">
            <result>/success.jsp</result>
</action>
 
这样当我们选中上传文件,提交的时候:文件内容会以File类型的方式放在image声明的变量中。文件的名字将会被放在imageFileName命名的变量中,文件的类型被放在imageContentType命名的变量中。
 
文件下载:
文件下载需要使用一个特殊的Result,stream类型的Result。Stream类型的Result主要用来处理文件下载操作。
处理原理为:所有的下载文件都是将一个二进制的流写入到HttpResponse中去。在Action类中定义一个InputSream类型的二进制流,在Result返回给用户的时候返回给用户。
 
扩展上述的代码,将上传来的文件直接下载给用户:
ImageUploadAction中需要追加一个InputSream类型的对象,并且指向上传的文件,代码如下,红色部分表示变化:
package com.jpleasure;
 
import com.opensymphony.xwork2.ActionSupport;
 
import java.io.File;
import java.io.InputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
 
public class ImageUploadAction extends ActionSupport {
 
    private File image;
    private String imageFileName;
    private String imageContentType;
 
    private InputStream imageInputStream = null;
 
 
    public InputStream getImageInputStream() {
        return imageInputStream;
    }
 
    public void setImageInputStream(InputStream imageInputStream) {
        this.imageInputStream = imageInputStream;
    }
 
    public File getImage() {
        return image;
    }
 
    public void setImage(File image) {
        this.image = image;
    }
 
    public String getImageFileName() {
       return imageFileName;
    }
 
    public void setImageFileName(String imageFileName) {
        this.imageFileName = imageFileName;
    }
 
    public String getImageContentType() {
        return imageContentType;
    }
 
    public void setImageContentType(String imageContentType) {
        this.imageContentType = imageContentType;
    }
 
 
    public String execute() {
 
        if (image != null) {
            System.out.println("file name is:" + this.imageFileName);
            System.out.println("file content type is:" + this.imageContentType);
            System.out.println("file length is:" + this.image.length());
 
            try {
                this.imageInputStream = new FileInputStream (image);
            } catch (FileNotFoundException e) {
               e.printStackTrace();          
 }
 
        }
 
        return SUCCESS;
    }
}
配置文件为,红色为变化部分:
<action name="imageUpload" class="com.jpleasure.ImageUploadAction">
            <result name="success" type="stream">
              <param name="contentType">image/pjpeg</param>
              <param name="inputName">imageInputStream</param>
              <param name="contentDisposition">attachment;filename="image.jpg"</param>
              <param name="bufferSize">1024</param>
            </result>
</action>
ContentType表示下载文件的类型。
InputName表示Action类中用来下载文件的字段的名字。
ContentDisposition用来控制文件下载的一些信息,包括是否打开另存对话框,下载文件名等。
BufferSize表示文件下载时使用的缓冲区的大小。
 
实际项目开发的考虑:
控制上传文件的类型和最大允许上传文件的size
使用File Upload Intercepter的参数可盈控制上传文件的类型和最大允许上传文件的size。例如:
<struts>
    <package name="myPackage" extends="struts-default">
 
        <interceptor-ref name="fileUpload">
            <param name="maximumSize">2MB</param>
            <param name="allowedTypes">text/html,image/jpeg</param>
        </interceptor-ref>
 
        <interceptor-ref name="basicStack"/>
 
        <action name="imageUpload" class="com.jpleasure.ImageUploadAction">
            <result name="success" type="stream">
                <param name="contentType">image/pjpeg</param>
                <param name="inputName">imageInputStream</param>
                <param name="contentDisposition">
attachment;filename="image.jpg"
</param>
                <param name="bufferSize">1024</param>
            </result>
        </action>
    </package>
</struts>
 
上述表示允许上传jpeg和html类型的文件,且最大文件上传size为2MB
 
显示错误信息:
可以使用如下key表示的message来显示文件上传出错的提示信息:

消息Key
说明
struts.messages.error.uploading
文件无法正常上传时的公共错误
struts.messages.error.file.too.large
文件大小超过最大允许size时的错误提示
struts.messages.error.content.type.not.allowed
文件类型不在上传文件允许类型中的错误提示


ExtJS教程- Hibernate教程-Struts2 教程-Lucene教程