文件上传和文件下载是我们在web应用程序中常用的两个功能,在java中,实现这两种功能的方式也有很多种,其中struts2就给我们提供了一种算是比较简单的方式吧,下面我们就一起来看一下,首先我们来看文件上传:
文件上传
文件上传我们首先应该注意的是在上传页面的表单,这个表单也是有讲究的,由于我们提交表单的数据中有文件上传,所以这个表单的所使用的编码类型就不能是原来的了,在这里我们应该使用的编码方式是multipart/form-data,并且数据提交方式要用post方式,下面我们具体来看一下:
Form.jsp:
<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中定义三个变量,这三个变量分别是文件、文件名,还有文件类型,如下:
private File file;
private String fileFileName;
private String fileContentType;
这三个变量的名字是有讲究的,不是随便命名就OK了,其中file这个变量名要和表单中文件的name要相同,fileFileName这个也是固定的,起名格式就是name+FileName,同样fileContentType也是如此,命名规则是name+ContentType,只有你按照命名规则来定义变量,struts2才能把文件上传相关信息收集起来。Ok,看完了变量设置,下面我们来看一下怎么struts2是怎么把文件上传到我们指定的位置的。那我们就先上代码,让代码帮我们来理解:
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的数组或列表。
< 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的代码应类似:
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; }
如果你想绑定到列表,则应类似:
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页面:
<body>
<h1>文件下载</h1>
<!-- 下载链接 -->
<s:a action="down.action">download</s:a>
</body>
页面很简单,就一下下载的链接,然后这个链接链接到我们的action中,下一步我们来看一下我们的action的编写:
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
{
return SUCCESS;
}
}
下面我们在来看一下struts.xml的配置:
<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表示XML,image/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配置:
<param name="contentDisposition">attachment;filename="${downloadFileName}"</param>
我们经常在中文下载中,出现文件名乱码的问题,这个问题是很多人都常见的,具体的很好的解决方法也没有,但我以前用的时候尝试着给他重新编码,这样可以解决大部分时候的中文下载乱码问题,但有时候也不行的。具体重新编码就是:
downFileName = new String(downFileName.getBytes(), "ISO8859-1");
好了,struts2文件上传和下载就简单介绍到这,文章中有什么不对或者错误的地方,欢迎大家指正。