一、目标:
实现一个只允许上传*.png *.bmp *.jpg *.jpeg *.gif图片的文件上传系统,如下图:
用户选定文件之后,点击上传按钮传到服务器的相应webapps工程的文件夹下的upload文件夹里面。
如果文件上传成功,则跳转至显示这个图片文件与用户在文件标题栏输入内容的页面,如下图:
如果文件上传失败,则在本页显示相关的出错信息:
二、基本思想:
与此前的struts基本工程没有太大地不同,只是在相应的Action多了几个必须处理的整型。同时在struts.xml要写入相应的拦截器拦截非图片类型的文件与对原版为英文的错误信息进行翻译。uploadsucc.jsp同样放WEB-里面,不上传成功不让看。
如图,整个系统是比较复杂的。不想ASP.NET使用C#开发,仅对一个文件上传控件写入代码就完事了。Struts中要对大量的页面进行编程。
三、具体实现过程
1.upload.jsp
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <%@ taglib uri="/struts-tags" prefix="s"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>简单的上传页面</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <!-- enctype="multipart/form-data"是存在着file空间的时候必须添加的。 struts2下的file空间很简单,与普通空间没什么区别,name是一会儿扔到方法内容所要操作的变量名称 label是控件之前的名字。 --> <s:form action="upload" method="post" enctype="multipart/form-data"> <s:textfield name="title" label="文件标题" /> <s:file name="upload" label="选择文件" /> <s:submit value="上传" /> </s:form> </body> </html>
与普通的表单没有太大的区别,主要是有一些小变化而已。配置好struts.xml之后,错误信息会在这个页面自动输出。
2.UploadAction.java
package com.ascent.struts2.action; import java.io.*;//写入文件的输入流需要 import org.apache.struts2.ServletActionContext;//取当前路径的时候需要 import com.opensymphony.xwork2.*;//要使用文件上传功能必须要此类 public class UploadAction extends ActionSupport { private String title; private File upload; /* Struts2中要求定义文件字段+FileName和+ContentType的两个字段来封装文件名与文件类型 这两个字段一会儿都要送到struts.xml中的拦截器进行处理*/ private String uploadFileName; private String uploadContentType; // 这是文件保存路径的字段,一会儿同样要送到struts.xml中进行处理 private String savePath; public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public File getUpload() { return upload; } public void setUpload(File upload) { this.upload = upload; } public String getUploadFileName() { return uploadFileName; } public void setUploadFileName(String uploadFileName) { this.uploadFileName = uploadFileName; } public String getUploadContentType() { return uploadContentType; } public void setUploadContentType(String uploadContentType) { this.uploadContentType = uploadContentType; } /* 关于文件保存路径SavePath的getter方法必须被改写,这样才能真正地获取上传文件的保存路径。 其中,旧版的ServletActionContext.getRequest().getRealPath(savePath);已经不再使用了 必须要改成如下的样子。*/ public String getSavePath() throws Exception { return ServletActionContext.getServletContext().getRealPath(savePath); } public void setSavePath(String savePath) { this.savePath = savePath; } public String execute() throws Exception { // 文件要输出到服务器的文件保存地址+原文件名的文件中,所以要定义这样的一个输出流 FileOutputStream fos = new FileOutputStream(this.getSavePath() + "\\" + this.getUploadFileName()); // 文件是从上传文件控件中读入的,所以要定义这样的一个输入流 FileInputStream fis = new FileInputStream(this.getUpload()); // 之后就是java经典的输入输出方法 byte[] buffer = new byte[1024]; int len = 0; while ((len = fis.read(buffer)) > 0) { fos.write(buffer, 0, len); } // System.out.println("结束上传!");这句写不写也罢,写就在Tomcat的服务器记录台上输出这样的一条记录 /* 无论文件上传之后是否会被struts.xml拦截,都先判定为成功, 反正都要放到struts.xml进行下一步的检验。*/ return SUCCESS; } }
注释已经写得很清楚,不再赘述。
3.struts.xml
<?xml version="1.0" encoding="GBK"?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1.7//EN" "http://struts.apache.org/dtds/struts-2.1.7.dtd"> <!-- 所谓的“指定Struts 2配置文件的根元素”,这段东西不一定要理解,但必须有,不然过不了tomcat的编译 --> <struts> <!--意思为:现在是开发中……这段没太大的意义 --> <constant name="struts.devMode" value="true" /> <!--指定上传临时文件的存放目录,必须自己手动在tomcat根目录下的...\bin文件夹下建立一个名为temp的文件夹 --> <constant name="struts.multipart.saveDir" value="temp" /> <!--指定国际化,也就是翻译错误信息的文件为此工程目录下的...src\message.properties, 这里千万别取诸如”messageResource“这类中间带大写字母的文件名, 亲测发现服务器无法读取这个国际化文件。 其中,这个国家化文件的编码为UTF-8 --> <constant name="struts.custom.i18n.resources" value="message"/> <constant name="struts.i18n.encoding" value="utf-8" /> <!--设置使用上传解析器的类型 --> <constant name="struts.multipart.parser" value="jakarta" /> <package name="upload" extends="struts-default"> <action name="upload" class="com.ascent.struts2.action.UploadAction"> <!--以上与平时没有太大的区别,以下为拦截器,设置拦截器允许格式,注意png文件与jpg文件的设置。 png要写为x-png,jpg有两个,一个jpg另一个pjpeg --> <interceptor-ref name="fileUpload"> <param name="allowedTypes">image/x-png,image/bmp,image/jpg,image/gif,image/pjpeg</param> </interceptor-ref> <!--所谓的”默认栈“,这行必须有 --> <interceptor-ref name="defaultStack"></interceptor-ref> <!--设置上传路径。 --> <param name="savePath">/upload</param> <result name="success">/WEB-INF/uploadsucc.jsp</result> <result name="input">/upload.jsp</result> </action> </package> </struts>
文件上传系统对于struts.xml的改动还是比较大的。
要添加很多行的代码来规范这个文件系统。
另外要注意对于tomcat目录下的设置。必须在其安装文件夹下的...\bin建立一个temp文件夹来安防上传临时文件,如C:\Program Files\apache-tomcat-7.0.6\bin
然后对...\conf\server.xml进行修改,如C:\Program Files\apache-tomcat-7.0.6\conf\server.xml。
找到 <Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
这几行,然后加入 URIEncoding="UTF-8",不然,你上传文件名带中文的图片无法被解析。也就是改成:
<Connector port="8080" protocol="HTTP/1.1" URIEncoding="UTF-8"
connectionTimeout="20000"
redirectPort="8443" />
4.uploadsucc.jsp
<%@ page language="java" import="java.util.*" import="java.net.*" pageEncoding="utf-8"%> <%@ taglib uri="/struts-tags" prefix="s"%> <% String path = request.getContextPath(); String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>上传成功页面</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> 上传成功! <br /> 文件标题: <s:property value="title" /> <br /> 文件为: <!-- 其中<s:property value="'upload/'+uploadFileName"/>为所上传文件的路径, 可以镶嵌在其余的html标签当中--> <img src="<s:property value="'upload/'+uploadFileName"/>" /> <a href="upload.jsp">返回</a> </body> </html>
弄好UploadAction.java与struts.xml之后,这个文件就很简单了。注释已经很清楚,不赘述。
以下为错误信息国际化。不做5与6,文件上传系统同样能用,只是上传诸如txt会在页面显示英文的错误信息,不美观而已。
5.在工程的src目录下新建一个struts.properties,里面就写一句话:
struts.custom.i18n.resources=message
意思是message是我翻译错误信息的文件。原版的错误信息是英文的,不利于阅读。
6.在工程的src目录下新建一个message.properties
里面写入:
struts.messages.error.uploading=\u4E0A\u4F20\u9519\u8BEF
struts.messages.error.file.too.large=\u6587\u4EF6\u8FC7\u5927
struts.messages.error.content.type.not.allowed=\u975E\u56FE\u5F62\u6587\u4EF6
那些\uXXXX皆为中文的utf-8码
建议,在MyEclipse的点开message.properties,再点击Add按钮name与values写入如下的参数即可。
自此,文件上传系统全部完成。