struts2 文件上传下载详解

文件上传
表单
文件上传的表单要求

  1. 表单提交的方式必须是POST
  2. 表单中必须有表单元素:或struts2标签<s:file label=“xxx” name=“xxx”/>
  3. 表单的enctype属性必须是multipart/form-data
    此处提供表单的enctype属性的3种值表示及其含义
    (1)application/x-www-form-urlencoded,默认值,它只能处理表单域里的value属性,采用这种编码方式的表单会将表单域的值处理成URL编码方式。
    (2)multipart/form-data,采用这种编码方式会以二进制流的方式来处理表单数据 ,这种编码方式会把文件域指定文件的内容也封装到请求参数里。
    (3)text/plain,这种编码方式当表单的action属性为mailto:URL的形式是比较方便,这种方式主要适用于直接通过表单发送邮件的方式。

1.表单样例
效果图
在这里插入图片描述
JSP代码:

<font color="red"><s:actionerror/></font>
<form action="${pageContext.request.contextPath}/UserAction_login"  "return check(this);" method="post" enctype="multipart/form-data">
	<table align="center" border="1">
		<tr>
			<td bgcolor="#bbbbbb">用户名:</td>
			<td><input type="text" name="id"/></td>
		</tr>
		<tr>
			<td bgcolor="#bbbbbb">密&nbsp;&nbsp;&nbsp;&nbsp;码:</td>
			<td><input type="password" name="pwd"/></td>
		</tr>
		<tr>
			<td bgcolor="#bbbbbb">照&nbsp;&nbsp;&nbsp;&nbsp;片:</td>
			<td><input type="file" name="photo"/></td>
		</tr>
		<tr>
			<td colspan="2" align="center"><input type="submit"  value="登录">&nbsp;&nbsp;<input type="reset" value="重置"></td>
		</tr>
		</table>
	</form>

若使用struts2标签,需要引入struts2标签库

<%@ taglib prefix="s" uri="/struts-tags"%>

2.action代码

package com.action;


import java.io.File;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.commons.io.FileUtils;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.valueBean.User;

public class UserAction extends ActionSupport{
	//封装除了文件的其他信息
	private String id;
	private String pwd;
	
	//封装上传的文件对象
	private File photo;
	//上传的文件类型   固定格式xxxContentType
	private String photoContentType;
	//上传的文件名   固定格式xxxFileName
	private String photoFileName;

	//生成唯一的文件名(该方法在上传的文件名不重复时可以不需要)
	private String uniqueFileName(String FileName) {
	
		//通过时间获得唯一的字符串(不修改日期时间情况下唯一)
		DateFormat format = new SimpleDateFormat("yyMMddHHmmss");
		String formatDate = format.format(new Date());
		
		//获得.最后出现的位置,分割文件名和后缀名
		int position = photoFileName.lastIndexOf(".");
		String extension = photoFileName.substring(position);
		
		return formatDate + extension;
	}
	
	//处理请求的方法
	public String login() throws Exception {
		//判断登录信息(为了方便理解,这里使用固定的用户名密码判断)
		if(id.equals("admin") && pwd.equals("123456")) {	
			ActionContext.getContext().getSession().put("id","admin");
			/*
			 *获得存放的绝对路径(注意,如果存放在项目的文件夹下服务器重启会消失,
			 * 若要永久保存,可放至固定目录如:String realPath = "c:/images";)
			*/
			String realPath = ServletActionContext.getServletContext().getRealPath("/photo");
			//自动生成唯一的文件名(若文件名不重复时可使用一下注释的代码并不需要编写 uniqueFileName方法)
			String realFileName = uniqueFileName(photoFileName);
			File real = new File(realPath,realFileName);
			//不重复时代码
			/*
			File real = new File(realPath,photoFileName);
			*/
			
			//判断路径是否存在,不存在的话自动创建
			if(photo != null)
				if(!real.getParentFile().exists())
					real.getParentFile().mkdirs();
					
			//拷贝photo文件内容到real
			FileUtils.copyFile(photo, real);
			
			return "loginSuccess";
			}
		else {
			ActionContext.getContext().put("error", "用户名或密码错误!");
			return "loginLose";
		}	
	}
	
	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getPwd() {
		return pwd;
	}

	public void setPwd(String pwd) {
		this.pwd = pwd;
	}

	public File getPhoto() {
		return photo;
	}
	public void setPhoto(File photo) {
		this.photo = photo;
	}
	public String getPhotoContentType() {
		return photoContentType;
	}
	public void setPhotoContentType(String photoContentType) {
		this.photoContentType = photoContentType;
	}
	public String getPhotoFileName() {
		return photoFileName;
	}
	public void setPhotoFileName(String photoFileName) {
		this.photoFileName = photoFileName;
	}
}

3.配置文件struts.xml信息

<struts>
	<package name="login" namespace="/" extends="struts-default">
			<action name="UserAction_*" class="com.action.UserAction" method="{1}">
				<result name="loginSuccess">/welcome.jsp</result>
				<result name="loginLose" >/login.jsp</result>
				<!-- 错误信息返回页面  -->
				<result name="input">/{1}.jsp</result>
			</action>
		</package>
	</struts>

4.设置允许提交的文件类型(后缀名)和文件大小最大值

<struts>
	<!-- 设置最大允许上传的文件大小(字节),默认2M
	<constant name="struts.multipart.maxSize" value="20480000"></constant>
	  -->
	<package name="login" namespace="/" extends="struts-default">
			<action name="UserAction_*" class="com.action.UserAction" method="{1}">
			<interceptor-ref name="defaultStack">
				<!-- 设置允许上传的文件类型(允许使用通配符) -->
				<param name="fileUpload.allowedTypes">image/*</param>
				
				<!-- 设置允许上传的文件后缀名
				<param name="fileUpload.allowedExtensions">.jpg,.png</param>
				 -->
			</interceptor-ref>
				<result name="loginSuccess">/welcome.jsp</result>
				<result name="loginLose" >/login.jsp</result>
				<!-- 错误信息返回页面  -->
				<result name="input">/{1}.jsp</result>
			</action>
		</package>
	</struts>

配置后需要显示错误需要在跳转到的页面使用<s:actionerror></s:actionerror>显示

5.设置错误中文显示
熟悉,拆分错误提示
在这里插入图片描述
如图,错误序号
0:字段名
1.文件名
2.临时文件名
3.文件类型

默认错误信息提示位置在struts2-core.jar\org.apache.struts2\struts-message.properties
在这里插入图片描述
图纸为几个国家的错误默认提示信息(无中文)

以struts-messages_en.properties为例展开
可见其中错误提示信息为值键组成
在这里插入图片描述
图片中三行代码为较常用的错误显示
31.文件超过最大值
32.文件类型不是允许提交的类型
33.文件后缀名不是允许提交的后缀名
其中{0},{1},{2},{3}对应于前面错误信息图的错误序号

理解以后,我们在src(或src包下)创建UserUpload.properties(xxx.properties)文件,然后可以模仿默认的信息编写自定义的错误提示信息(系统会将输入的中文转换成16进制)
示例内容

struts.messages.error.content.type.not.allowed="{1}"\u4E0D\u662F\u56FE\u7247\u7C7B\u578B
struts.messages.error.file.extension.not.allowed="{1}"\u540E\u7F00\u540D\u4E0D\u6EE1\u8DB3\u683C\u5F0F

必须在struts.xml配置国际化,才会生效
添加后struts.xml代码为

<struts>
	<!-- 配置国际化 -->
	<constant name="struts.custom.i18n.resources" value="UserUpload"></constant>
	<!-- 设置最大允许上传的文件大小(字节),默认2M
	<constant name="struts.multipart.maxSize" value="20480000"></constant>
	  -->
	<package name="login" namespace="/" extends="struts-default">
			<action name="UserAction_*" class="com.action.UserAction" method="{1}">
			<interceptor-ref name="defaultStack">
				<!-- 设置允许上传的文件类型(允许使用通配符) -->
				<param name="fileUpload.allowedTypes">image/*</param>
				
				<!-- 设置允许上传的文件后缀名
				<param name="fileUpload.allowedExtensions">.jpg,.png</param>
				 -->
			</interceptor-ref>
				<result name="loginSuccess">/welcome.jsp</result>
				<result name="loginLose" >/login.jsp</result>
				<!-- 错误信息返回页面  -->
				<result name="input">/{1}.jsp</result>
			</action>
		</package>
	</struts>

演示图片
在这里插入图片描述

6.多文件上传(此处给出步骤,不详细介绍)
1.多文件上传只需在JSP中设置多个文件上传元素或struts2标签<s:file label=“xxx” name=“xxx”/>
2.action代码中接收文件的三个字段均改为数组类型(重新注入get,set方法)
3.处理部分逻辑

文件下载(此处使用动态下载,若使用静态,只需要把fileName用固定值替换即可)
相对于文件上传,文件下载就显得简单得多(个人认为)
文件下载使用的其实就是一种结果类型(Stream)
JSP代码

	<s:form action="UserAction_download">
	<s:textfield label="输入下载的文件名(含后缀名)" name="fileName"/>
	<s:submit value="下载"></s:submit>
	</s:form>

action代码

package com.action;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import com.opensymphony.xwork2.ActionSupport;
public class UserAction extends ActionSupport{
	//提供输入流,需要get方法,set文件下载时方法可有可无
	private InputStream inputStream;
	private String fileName;
	public String download() throws FileNotFoundException, UnsupportedEncodingException {
		//将文件转为输入流
		String path = "H:/JAVAEE/images/" + fileName;
		inputStream = new FileInputStream(path);
		
		//由于重新转到网页,所以文件名含中文时需要行url转码
		fileName = URLEncoder.encode(fileName,"UTF-8");
		return "download";
	}
	public String getFileName() {
		return fileName;
	}
	public void setFileName(String fileName) {
		this.fileName = fileName;
	}
	public InputStream getInputStream() {
		return inputStream;
	}
}

struts.xml代码

<struts>
	<package name="login" namespace="/" extends="struts-default">
		<action name="UserAction_*" class="com.action.UserAction" method="{1}">
					<result name="download" type="stream">
						<!-- 配置输出流 -->
						<param name="inputName">inputStream</param>
						<!-- 设置响应头消息,使浏览器以下载方式打开 固定格式:attachment;filename=xxx  -->
						<param name="contentDisposition">attachment;filename=${fileName}</param>
						<!-- 设置响应头消息,告诉浏览器响应正文的MIME类型  固定格式:application/octet-stream -->
						<param name="contentType">application/octet-stream</param>
					</result>
		</action>
	</package>
</struts>

演示图片
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_42301302/article/details/88915822