Struts2 入门学习笔记(五)——上传下载

本文介绍Struts2框架中的文件上传与下载功能实现,包括单文件与多文件上传的处理方式,以及如何配置文件类型与大小限制,最后讲述文件下载的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Struts2 入门学习笔记(五)——上传下载

一.简介


首先要明确为了能进行上传,必须将表单设为POST,并且添加属性enctype="multipart/form-data",只有这样才能进行传送。当然,关于在struts.properties配置文件中关于上传时的上传解析器在此不做讲解,有想看的可以去配置文件查找,主要由以下三种,一般默认第三种:
#指定使用COS的文件上传解析器
#struts.multipart.parser=cos
#指定使用Pell的文件上传解析器
#struts.multipart.parser=pell
#指定使用JakartaCommon-fileUpload文件上传解析器
#struts.multipart.parser=jakarta

二.单文件上传


1. 实现文件上传的Action
首先写一个表单jsp:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
</head>
<body>
<s:form action="upload" enctype="multipart/form-data">
<s:textfield name="title" label="文件标题" />
<s:file name="upload" label="选择文件" />
<s:submit value="上传"/>
</s:form>
</body>
</html>
在struts2中框架负责解析HttpServletRequest请求的参数,包括文件域,Struts2使用File类型封装文件域,下面是Action:
package cn.sun.upload;
 
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
 
import org.apache.struts2.ServletActionContext;
 
 
import com.opensymphony.xwork2.ActionSupport;
 
public class Upload extends ActionSupport{
//封装文件标题请求参数成员
private String title;
//封装上传文件域的成员变量
private File upload;
//封装上传文件类型
private String uploadContentType;
//封装上传文件名的属性
private String uploadFileName;
//直接在struts.xml中配置的成员变量
private String savePath;
//所有的getter/setter方法+下面这个(单独写是因为它的get是从struts.xml中取到的
public String getSavePath() {
return ServletActionContext.getServletContext().getRealPath(savePath);
}
public void setSavePath(String savePath) {
this.savePath = savePath;
}
@Override
public String execute() throws Exception {
//以服务器的文件保存地址和原文件名简历上传文件输出流
FileOutputStream fos = new FileOutputStream(getSavePath()+"\\"+getUploadFileName());
FileInputStream fis = new FileInputStream(getUpload());
byte[] buf = new byte[1024];
int len = 0;
while( ( len=fis.read(buf) ) > 0){
fos.write(buf, 0, len);
}
return SUCCESS;
}
}

下一步自然区设置配置文件,将这个action放入进去,同时将上面这个中savePath地址传入:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<package name="myPackage" extends="struts-default">
<action name="upload" class="cn.sun.upload.Upload">
<param name="savePath">/uploadFiles</param>
<result name="success">/page/success.jsp</result>
</action>
</package>
</struts>

这里顺便设置一个success页面用来显示接收到的文件:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
</head>
<body>
This is my success page!<br>
文件标题:<s:property value=" + title"/><br>
文件为:<img src="<s:property value="'uploadFiles/'+uploadFileName"/>"/><br>
</body>
</html>
上述中文件名一致没有变化,建议真正保存的时候一定要用UUID工具将文件名唯一化保存,同时放弃文件名中的格式,这样保存的就是一个不可执行不可预览文件,提取时通过uploadFileContentType去还原文件类型。
文件不可轻易上传,有的文件万一有问题会影响系统的运行,或者有些东西是不允许上传的,或者文件大小要设限制等等,所以这里也需要一个过滤器来对上传文件进行一个过滤,通常有两种方法解决这个问题,一种是手动实现,在struts.xml文件中配置param放置允许上传类型,在action中提取后进行对比,有则上传,没有则返回异常或者错误界面;第二种是常见的过滤器设置,这里用拦截器实现文件的过滤,strtut2自带文件拦截器,我们只需要修改很少的代码就可以实现。。或者,还记得么,添加自己的拦截器,在自己的拦截器栈里加入自己的拦截器和默认拦截器栈,大功告成!
这里使用struts自带的拦截器,在struts.xml中添加:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<package name="myPackage" extends="struts-default">
<action name="upload" class="cn.sun.upload.Upload">
<!-- 配置fileUpload的拦截器 -->
<interceptor-ref name="fileUpload">
<!-- 配置允许的上传文件类型 -->
<param name="allowedTypes">image/png,image/gif,image/jpeg</param>
<!-- 配置允许的上传文件大小 -->
<param name="maximumSize">200000</param>
</interceptor-ref>
<!-- 配置系统默认拦截器栈 -->
<interceptor-ref name="defaultStack" />
<!-- 添加属性 -->
<param name="savePath">/uploadFiles</param>
<result name="input">/page/fail.jsp</result>
<result name="success">/page/success.jsp</result>
</action>
</package>
</struts>
来一个失败页面:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head></head>
<body>
This is my fail page. <br>
<s:fielderror />
</body>
</html>
然后我们就可以去测定试一下了,结果上传成功

三.多文件上传

原理就是上面的那个,只不过多加了几次而已,这里只写几句话:
<title>Insert title here</title>
<script type="text/javascript">
function addFileUploadItem(){
var itemTdObj = document.getElementById("itemTdId");
//将原有的td中内容,添加一个字符串,设置回td
itemTdObj.innerHTML = itemTdObj.innerHTML + "<br/><span>选择文件:<input type=\"file\" name=\"image\" /></span>";
}
</script>
</head>
<body>
<!-- 使用JavaScript追加上传选择 -->
<a href="javascript:void(0)" onclick="addFileUploadItem()">添加上传选择</a>
<s:actionerror/>
<form action="${pageContext.request.contextPath}/uploadDemo02Action" method="post" enctype="multipart/form-data">
<table>
<tr>
<td id="itemTdId">
<span>选择文件:<input type="file" name="image" /></span>
</td>
</tr>
<tr>
<td><input type="submit" value="多文件上传"/></td>
</tr>
</table>
</form>
</body>

编写action提供字段及setter,接收多个文件时,需要提供数组获得。

//提供接收的数据类型是数组即可。
//#1 文件内容
private File[] image;
//#2文件名称
private String[] imageFileName;
//#3文件类型
private String[] imageContentType;
//#4 setter方法
public void setImage(File[] image) {
this.image = image;
}
public void setImageFileName(String[] imageFileName) {
this.imageFileName = imageFileName;
}
public void setImageContentType(String[] imageContentType) {
this.imageContentType = imageContentType;
}

public void add() throws Exception {
//父目录
String parentDir = ServletActionContext.getServletContext().getRealPath("/WEB-INF/upload");
//遍历所有内容,并保存
for(int i = 0 ; i < image.length ; i ++){
// 1 文件内容
File singleImage = image[i];
// 2 文件名称
String singleFileName = imageFileName[i];
// 3 保存
File file = new File(parentDir , singleFileName);
FileUtils.copyFile(singleImage, file); // (流自动关闭,父目录自动创建)
}
}




    提供国际资源文件

    位置:当前类包下建立国际化文件/UploadDemo02Action.properties

    内容:

struts.messages.upload.error.SizeLimitExceededException=\u6587\u4EF6\u4E0A\u4F20\u5927\u5C0F\u8D85\u8FC7\u9650\u5B9A,\u5B9E\u9645\u5927\u5C0F{1}\uFF0C\u9650\u5B9A\u7684\u6700\u5927\u503C{0}

 properties文件的key固定的,来自 struts2-core-2.3.15.3.jar!/org/apache/struts2/struts-messages.properties

四.下载

下载实现比较简单,有许多种方法,但是为什么用struts呢,因为有很好的控制性,权限之类的问题。
我们这里写一个实例来让大家明白下它的操作流程,首先编写action类:
package cn.sun.upload;
 
import java.io.InputStream;
 
import org.apache.struts2.ServletActionContext;
 
import com.opensymphony.xwork2.ActionSupport;
 
public class FileDownloadAction extends ActionSupport {
private String inputPath;
public void setInputPath(String inputPath) {
this.inputPath = inputPath;
}
//get方法在后面也有用
public InputStream getTargetFile() {
 
return ServletActionContext.getServletContext().getResourceAsStream(inputPath);
}
 
}

这里面我们定义了一个方法用来输出指定位置的文件流,只需要在其他地方使用该方法即可。
配置action类型的结果需要制定以下四个属性:
contentType 指定被下载文件的文件类型
inputName 指定被下载文件的入口输入流
contentDisposition 指定下载的文件名
bufferSize 下载缓冲大小
对应在struts.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<package name="myPackage" extends="struts-default">
<action name="download" class="cn.sun.upload.FileDownloadAction">
<param name="inputPath">/uploadFiles/1.jpg</param>
<result type="stream">
<!-- 指定下载文件类型 -->
<param name="contentType">image/jpg</param>
<!-- 指定由getTargetFile()方法返回被下载的文件inputstream流 -->
<param name="inputName">targetFile</param>
<param name="contentDisposition">attachment;filename=1.jpg</param>
<param name="bufferSize">4096</param>
</result>
</action>
</package>
</struts>


中文乱码问题:
        当我们希望下载中文的文件名时,和刚才不一样,刚才直接写死了下载的文件地址和文件名,一般情况下在action中应该这样写就可以避免乱码:
package cn.sun.upload;
 
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
 
import org.apache.struts2.ServletActionContext;
 
import com.opensymphony.xwork2.ActionSupport;
 
public class FileDownloadAction extends ActionSupport {
private String inputPath;
public void setInputPath(String inputPath) {
this.inputPath = inputPath;
}
//////////////////////////////////////
private String imageFileName;
public String getImageFileName() throws UnsupportedEncodingException {
return new String(imageFileName.getBytes(),"ISO-8859-1");
}
/////////////////////////////////////
public InputStream getTargetFile() {
 
return ServletActionContext.getServletContext().getResourceAsStream(inputPath);
}
 
}

同理,在struts.xml中配置的时候刚才我们直接写得文件名,现在我们将获取到的文件名用表达式写出来而不是直接写汉语:
<action name="download" class="cn.sun.upload.FileDownloadAction">
<param name="inputPath">/uploadFiles/1.jpg</param>
<result type="stream">
<!-- 指定下载文件类型 -->
<param name="contentType">image/jpg</param>
<!-- 指定由getTargetFile()方法返回被下载的文件inputstream流 -->
<param name="inputName">targetFile</param>
<!--<param name="contentDisposition">attachment;filename=1.jpg</param>-->
<param name="contentDisposition">attachment;filename=${imageFileName}</param>
<param name="bufferSize">4096</param>
</result>
</action>
为什么我们在上面写一句${imageFileName}就可以收到文件名?这是因为在action中我们有一个getter方法,通过此方法就可以在xml中读取到数值,这是OGNL表达式






















资源下载链接为: https://pan.quark.cn/s/9648a1f24758 这个HTML文件是一个专门设计的网页,适合在告白或纪念日这样的特殊时刻送给女朋友,给她带来惊喜。它通过HTML技术,将普通文字转化为富有情感和创意的表达方式,让数字媒体也能传递深情。HTML(HyperText Markup Language)是构建网页的基础语言,通过标签描述网页结构和内容,让浏览器正确展示页面。在这个特效网页中,开发者可能使用了HTML5的新特性,比如音频、视频、Canvas画布或WebGL图形,来提升视觉效果和交互体验。 原本这个文件可能是基于ASP.NET技术构建的,其扩展名是“.aspx”。ASP.NET是微软开发的一个服务器端Web应用程序框架,支持多种编程语言(如C#或VB.NET)来编写动态网页。但为了在本地直接运行,不依赖服务器,开发者将其转换为纯静态的HTML格式,只需浏览器即可打开查看。 在使用这个HTML特效页时,建议使用Internet Explorer(IE)浏览器,因为一些老的或特定的网页特效可能只在IE上表现正常,尤其是那些依赖ActiveX控件或IE特有功能的页面。不过,由于IE逐渐被淘汰,现代网页可能不再对其进行优化,因此在其他现代浏览器上运行可能会出现问题。 压缩包内的文件“yangyisen0713-7561403-biaobai(html版本)_1598430618”是经过压缩的HTML文件,可能包含图片、CSS样式表和JavaScript脚本等资源。用户需要先解压,然后在浏览器中打开HTML文件,就能看到预设的告白或纪念日特效。 这个项目展示了HTML作为动态和互动内容载体的强大能力,也提醒我们,尽管技术在进步,但有时复古的方式(如使用IE浏览器)仍能唤起怀旧之情。在准备类似的个性化礼物时,掌握基本的HTML和网页制作技巧非常
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值