您的位置:首页 > 编程语言 > Java开发

木其工作室代写程序 [原]Struts2 实现上传附件(支持多附件)

2013-07-27 13:15 375 查看
淘宝网上专业IT程序代写

原创作品,允许转载,转载时请务必以超链接形式标明文章
原始出处 、作者信息和本人声明。否则将追究法律责任。

作者:永恒の_☆ 地址:/article/2048093.html

一、简单介绍

使用Struts2上传附件功能非常容易实现,只需要使用普通的Action类 用来获取上传的附件对象,然后保存到指定的路径下即可。基本原理和Servlet上传附件一样,只不过封装附件的方式实现不一样罢了。servlet上传附件的地址:http://blog.csdn.net/ch656409110/article/details/9502143

二、准备条件

准备一个struts2环境的项目

common-io.jar ,下载地址:http://commons.apache.org/io/download_io.cgi

common-upload.jar ,下载地址:http://jakarta.apache.org/commons/fileupload/

三、实现思路

准备一个上传附件的页面,代码如下:

<form name="saveForm" action="${ctx}/house/save.action" method="post" onsubmit="return checkSaveHouseForm();" enctype="multipart/form-data">
<tr>
<td class="field">上传附件:</td>
<td>
<input type="file" name="upload" class="text" onblur="checkUpload()"/>
<span id="sp_upload" class="message"></span>
<br />
</td>
</tr>
<tr>
<td class="field">附件名称:</td>
<td>
<input type="text" name="fileName" class="text"/>
</td>
</tr>
<div class="buttons"><input type="submit" name="submit" value="发布"/></div>
</form>
页面中定义的附件控件名称是 upload,那么在Action类中也要定义相同的upload属性,如下:

private File upload;   //upload file
private String uploadFileName;   //附件名称
private String uploadContentType; //附件类型
private String savePath;    //附件保存的路径
private List<String> fileName ;  //用户输入的名称
//省略get set方法

需要注意的是,如果定义附件对象的附加属性,要以附件对象为前缀,比如upload为名的附件。

并且savePath的get方法要去读取才能获得,代码如下:

public synchronized String getSavePath() {
return ServletActionContext.getServletContext().getRealPath(savePath);
}


封装好对象之后,接下来处理业务逻辑,具体代码如下:

//处理上传的附件
System.err.println(upload.getAbsolutePath());
System.err.println(upload.getName());
System.err.println(uploadFileName);

fileName = fileName + uploadFileName.substring(uploadFileName.lastIndexOf("."));
File target = new File(getSavePath(), fileName);
//直接调用org.apache.commons.io.FileUtils下的copyFile 将上传的附件复制到指定的目录下
//FileUtils.copyFile(upload, target);

//另外还可以通过输入流读取字符之后 用输出流写入到磁盘中也是一样的。
OutputStream outputStream = new FileOutputStream(new File(getSavePath(),fileName));
InputStream inputStream = new FileInputStream(getUpload());

byte[] buffers = new byte[1024];
int length = 0;
while((length = inputStream.read(buffers))!=-1){
outputStream.write(buffers, 0, length);
}
inputStream.close();
outputStream.close();

house.setAttachUrl(savePath + Constant.SEPARATOR + fileName);
houseBiz.saveHouse(house);

ServletActionContext.getRequest().setAttribute("attachurl", house.getAttachUrl());


上面代码中 有两种实现将上传的附件放到指定目录的方法,都可以实现的。另外第一种更加方便一些,直接调用org.apache.commons.io.FileUtils下的copyFile 将上传的附件复制到指定的目录下。

然后struts.xml配置文件中需要配置一下我们action的跳转,以及附件保存路径等等信息,具体如下:

<package name="house" namespace="/house" extends="struts-default">
<action name="*" class="com.struts2.web.action.HouseAction" method="{1}">
<result name="listPage">/WEB-INF/system/page/house_list.jsp</result>
<result name="detail">/WEB-INF/system/page/house_detail.jsp</result>
<result name="detail">/WEB-INF/system/page/house_detail.jsp</result>
<result name="loadSuccess">/WEB-INF/system/page/saveHouse.jsp</result>

<param name="savePath">/attach</param>
<interceptor-ref name="defaultStack">
<!-- 配置允许上传的文件类型,多个用","分隔 -->
<param name="fileUpload.allowedTypes">
image/bmp,image/png,image/gif,image/jpeg,image/jpg ,image/x-png, image/pjpeg
</param>
<!-- 配置允许上传的文件大小,单位字节 -->
<param name="fileUpload.maximumSize">102400</param>
</interceptor-ref>
<result name="saveSuccess">/WEB-INF/system/page/saveHouseSuccess.jsp</result>
<result name="input">/WEB-INF/system/page/saveHouseFail.jsp</result>
</action>
</package>


这里需要指定上传的附件指定的位置,即加一个<param>标签就好了,然后指定 上传的附件的限制类型、以及上传大小。

然后下面这种配置 是网上很多,反正我试了很多次,都不起作用。

<interceptor-ref name="fileUpload">
<param name="allowedTypes">image/jpg,image/png,image/gif,image/jpeg,image/pjpeg</param>
<param name="maximunSize">10000</param>
</interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>


实践证明 <interceptor-ref name="defaultStack"></interceptor-ref> 必须加上,否则接收的所有参数都为null,因为上面有引用fileUpload这个拦截器。

接下来就可以部署项目,启动服务器运行了。

首先选择附件,效果如下:



选择发布按钮,然后服务器就会进行上传操作。效果如下:



然后 在控制台可以在到action中输出的上传附件信息。效果如下:



可见,在请求提交后服务器先把附件放在服务器的一个临时文件夹下,当真正上传成功后就会把该临时文件删除。

这样,使用struts2上传单个文件效果完成了。

四、多附件上传

接下来看看多附件上传,在upload上传页面肯定需要多个file控件,代码如下:

<form name="saveForm" action="${ctx}/house/save.action" method="post" onsubmit="return checkSaveHouseForm();" enctype="multipart/form-data">
<tr>
<td class="field">上传附件:</td>
<td>
<input type="file" name="upload" class="text" onblur="checkUpload()"/>
<span id="sp_upload" class="message"></span>
<br />
</td>
</tr>
<tr>
<td class="field">附件名称:</td>
<td>
<input type="text" name="fileName" class="text"/>
</td>
</tr>
<tr>
<td class="field">上传附件:</td>
<td>
<input type="file" name="upload" class="text"/>
<br />
</td>
</tr>
<tr>
<td class="field">附件名称:</td>
<td>
<input type="text" name="fileName" class="text" onblur="checkFileName()"/>
<span id="sp_fileName" class="message"></span>
</td>
</tr>
</table>
<div class="buttons"><input type="submit" name="submit" value="发布"/></div>
</form>
较上面而言 仅仅多了一个附件控件 和 附件名称控件。

然后后台需要改了,原先单个附件上传可以定义FIle 类型的对象接收参数,现在可是多个。所以需要重新定义属性,代码如下:

private List<File> upload;   //upload file
private List<String> uploadFileName;   //附件名称
private List<String> uploadContentType; //附件类型
private String savePath;    //附件保存的路径
private List<String> fileName ;  //用户输入的名称
//省略了get set 方法


实践 发现,这里定义 List 类型或者该属性原有类型的数组 都可以接收成功,可见struts2还是蛮强大的。

比如:

private File[] upload;   //upload file
private String[] uploadFileName;   //附件名称
private String[] uploadContentType; //附件类型
private String savePath;    //附件保存的路径
private String[] fileName ;  //用户输入的名称
//省略了get set 方法


然后处理上传的时候需要用循环来依次上传,具体代码如下:

//处理上传的附件
if(upload!=null){
for (int i=0; i<upload.size(); i++) {
fileName.set(i, fileName.get(i) + uploadFileName.get(i).substring(uploadFileName.get(i).lastIndexOf(".")));
File target = new File(getSavePath(), fileName.get(i));
//直接调用org.apache.commons.io.FileUtils下的copyFile 将上传的附件复制到指定的目录下
//FileUtils.copyFile(upload, target);

//另外还可以通过输入流读取字符之后 用输出流写入到磁盘中也是一样的。
OutputStream outputStream = new FileOutputStream(new File(getSavePath(),fileName.get(i)));
InputStream inputStream = new FileInputStream(getUpload().get(i));

byte[] buffers = new byte[1024];
int length = 0;
while((length = inputStream.read(buffers))!=-1){
outputStream.write(buffers, 0, length);
}
inputStream.close();
outputStream.close();
if(house.getAttachUrl()!=null && !house.getAttachUrl().equals("")){
house.setAttachUrl(house.getAttachUrl() + "," + savePath + Constant.SEPARATOR + fileName.get(i));
}else{
house.setAttachUrl(savePath + Constant.SEPARATOR + fileName.get(i));
}
}
}
houseBiz.saveHouse(house);

ServletActionContext.getRequest().setAttribute("attachurl", house.getAttachUrl());


ok,再重新部署,启动服务器然后在执行一遍,效果如下图:



点击发布按钮,效果如下:



界面上是成功了,然后在去附件指定目录查看 是否真正成功。

这样,多附件上传就成功完成了。

五、限制上传的附件类型和大小

前面已经配置的很清楚了,当我们想要过滤一些不好的情况,比如上传附件的大小上限,以及类型的限制。可以先在前台判断,当然如果前台被屏蔽了 就只能通过后台再次判断上传的附件是否满足需求,否则服务器会被搞垮的。

当附件的大小超过上限,默认的2M大小,如果给超过上限 就不会传到服务器,服务器不会抛出异常,进入sturts.xml中配置的input对应的页面,然后可以在页面中添加

<s:fielderror></s:fielderror> 标签捕捉具体异常。

具体异常信息显示如下图所示:



当上传的附件不是图片格式的话,也不会上传到服务器,会显示如下结果:



这样子显示好吗?感觉不太友好,全是一片英文字母。所以为了友好显示后台抛出的异常可以这样:

在处理上传附件的Action中重写addActionError(),当异常类型是超出上限的时候我就修改提示,具体代码如下:

@Override
public void addActionError(String anErrorMessage) {
if (anErrorMessage.startsWith("the request was rejected because its size")) {
super.addActionError("抱歉,你上传的文件超过了上限 !!");
} else {
super.addActionError(anErrorMessage);
}
}

说实话,这种方式在我以前的项目中可以实现,但是这里一直不成功,我也不知道为什么。。。。

不过可以用另一种方法,给struts指定一个属性文件,比如struts.properties ,直接放在classpath的根目录下。

例子如下:

struts.messages.error.content.type.not.allowed=\u62B1\u6B49\uFF0C\u60A8\u4E0A\u4F20\u7684\u9644\u4EF6\u4E0D\u662F\u56FE\u7247\u683C\u5F0F\u7684\uFF01
struts.messages.error.file.too.large=\u62B1\u6B49\uFF0C\u60A8\u4E0A\u4F20\u7684\u9644\u4EF6\u592A\u5927\uFF0C\u6700\u591A10M!
struts.messages.error.uploading=\u62B1\u6B49\uFF0C\u4E0A\u4F20\u51FA\u9519\u4E86\uFF01
然后在struts的配置文件中指定一下,就好了,具体如下:

<!-- 指定struts属性文件 -->
<constant name="struts.custom.i18n.resources" value="struts" />


然后在试试看就会发现效果以前好多了,如下图:



这个是附件太大的友好提示,因为传了两个附件,所有显示了两个。



这个是附件类型错误的友好提示。

六、实现下载功能

其实这个下载功能和在Servlet 中处理的实现方式一样,所以不在累赘。servlet上传附件的地址:http://blog.csdn.net/ch656409110/article/details/9502143

作者:ch656409110 发表于2013-7-27 13:15:24 原文链接

阅读:4269 评论:0 查看评论
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: