Servlet实现下载

1、Servlet 3.1之前实现文件上传

package ecut.request;

import java.io.BufferedReader;
import java.io.IOException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; public class FirstUploadServlet extends HttpServlet { private static final long serialVersionUID = -7777691027208490971L; @Override
protected void doGet( HttpServletRequest request , HttpServletResponse response ) throws ServletException, IOException {
throw new RuntimeException( "不支持GET方式上传" );
} @Override
protected void doPost( HttpServletRequest request , HttpServletResponse response ) throws ServletException, IOException { request.setCharacterEncoding( "UTF-8" ); // 上传文件时,只考虑文本文件,不考虑其它文件
BufferedReader reader = request.getReader();
//InputStream in = request.getInputStream(); String s ;
while( ( s = reader.readLine() ) != null ){
System.out.println( s );
} } }

2、Servlet 3.1 开始实现文件上传

package ecut.request;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part; public class SecondUploadServlet extends HttpServlet { private static final long serialVersionUID = 4485463572490572537L; @Override
protected void doGet( HttpServletRequest request , HttpServletResponse response ) throws ServletException, IOException {
throw new RuntimeException( "不支持GET方式上传" );
} @Override
protected void doPost( HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException { // String username = request.getParameter( "username" ) ; // <input type="text" name="username" > Part part = request.getPart( "upfile" ) ; // <input type="file" name="upfile" >
System.out.println( part ); /* Servlet 3.0 中获得文件名的做法
String cd = part.getHeader( "Content-Disposition" );
System.out.println( cd );
String s = "filename=\"";
int index = cd.indexOf( s );//找到filename的位置
String name = cd.substring( index + s.length() , cd.length() - 1 );//获取文件名
System.out.println( name );
*/ // part.getName() ; // name="upfile"
String filename = part.getSubmittedFileName(); // Servlet 3.1 开始出现的方法 part.write( filename ); } }

Struts2实现下载

1、首先在配置文件中指定存储位置storePath,在配置文件中action标签中通过 param 为 当前的 Action 实例 指定一个参数 ,实际上是 Action 类中的一个 属性 。

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd"> <struts>
<package name="upload" namespace="/upload" extends="struts-default" > <action name="action/single" class="ecut.upload.SingleFileUploadAction" >
<!-- 通过 param 为 当前的 Action 实例 指定一个参数 ( 实际上是 Action 类中的一个 属性 ) -->
<param name="storePath">D:/</param> <result name="success" type="redirectAction">
<param name="actionName">success/single</param>
</result>
<result name="fail" type="redirectAction">
<param name="actionName">fail/single</param>
</result>
</action>
</struts>

2、struts.xml中的包继承了struts-default包,struts-default包中指定了默认的拦截器栈,里面有一个fileUpload interceptor,Struts 2实现文件上传就是由这个拦截器来实现的。所以在struts.xml中最好先引用一下默认拦截器。

3、参照fileUpload interceptor api 的完成Action类的编写,由图中可知需要添加以下参数

  • [File Name] : File - 实际文件名,和页面的文件名相对应,表单中是xxx,则Action类中也要有xxx属性,且名称保持一致
  • [File Name]ContentType : String - 文件的内容类型,命名前缀得和文件名称保持一致,xxxContentType
  • [File Name]FileName : String -上传文件的实际名称,命名前缀得和文件名称保持一致,xxxFileName

Jsp代码:

<%@ page language = "java" pageEncoding = "UTF-8" %>
<%@ page contentType = "text/html; charset= UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Struts Upload</title>
</head>
<body> <h5>文件上传</h5>
<!-- method 必须是 POST ,enctype 必须是 multipart/form-data -->
<form action="${ pageContext.request.contextPath }/upload/action/single" method="post" enctype="multipart/form-data">
<input type="file" name="upload" >
<input type="submit" value="上传" >
</form>
</body>
</html>

Action类代码:

package ecut.upload;

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import com.opensymphony.xwork2.Action; public class SingleFileUploadAction implements Action { private static Logger logger = LogManager.getLogger();
//保存文件的位置,上传文件到那个目录
private String storePath ;
// [File Name] : File - the actual File,与表单中的name保持一致
private File upload ;
// [File Name]ContentType : String - the content type of the file,文件内容类型
private String uploadContentType ;
// [File Name]FileName : String - the actual name of the file uploaded (not the HTML name),实际的文件名
private String uploadFileName ; @Override
public String execute() throws Exception {
//临时文件
logger.info( "upload : " + upload );
logger.info( "content type : " + uploadContentType );
logger.info( "file name : " + uploadFileName ); //getCanonicalPath获取规范化路径
Path source = Paths.get( upload.getCanonicalPath() ); Path target = Paths.get( this.storePath , uploadFileName ); //Replace an existing file if it exists.
Files.copy( source , target , StandardCopyOption.REPLACE_EXISTING ); return SUCCESS;
} public String getStorePath() {
return storePath;
} public void setStorePath(String storePath) {
this.storePath = storePath;
} public File getUpload() {
return upload;
} public void setUpload(File upload) {
this.upload = upload;
} public String getUploadContentType() {
return uploadContentType;
} public void setUploadContentType(String uploadContentType) {
this.uploadContentType = uploadContentType;
} public String getUploadFileName() {
return uploadFileName;
} public void setUploadFileName(String uploadFileName) {
this.uploadFileName = uploadFileName;
} }

Struts2  上传文件是先生成一个临时文件保存在临时目录下,上传成功后临时文件消失。

4、上传默认的最大尺寸是,在 default.properties 中默认定义的大小是 2MB ,修改默认上传最大尺寸可以在xml中配置,可以指定全局的常量,也可以在action标签中设置某个action最大上传尺寸(struts.multipart.maxSize >= fileUpload.maximumSize )。

struts.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd"> <struts> <!-- 允许在 action 的 名称 中使用 / 字符 -->
<constant name="struts.enable.SlashesInActionNames" value="true" />
<!-- 启用动态方法调用 <constant name="struts.enable.DynamicMethodInvocation" value="true" /> --> <!-- 修改 action 请求路径的后缀 -->
<constant name="struts.action.extension" value="do,," />
<!-- 解析器的作用是对request.getInputStream()返回的字节流进行解析获取文件内容、类型、名称(和resultType="stream" 实现下载原理一致) -->
<!-- 指定 对上传的 字节流进行解析的解析器 : jakarta 、cos 、pell -->
<constant name="struts.multipart.parser" value="jakarta" />
<!-- 指定上传文件的尺寸 ( 在 default.properties 中默认定义的大小是 2MB )-->
<constant name="struts.multipart.maxSize" value="2097152000" /> <package name="upload" namespace="/upload" extends="struts-default" > <action name="action/single" class="ecut.upload.SingleFileUploadAction" >
<!-- 通过 param 为 当前的 Action 实例 指定一个参数 ( 实际上是 Action 类中的一个 属性 ) -->
<param name="storePath">D:/</param> <result name="success" type="redirectAction">
<param name="actionName">success/single</param>
</result>
<result name="fail" type="redirectAction">
<param name="actionName">fail/single</param>
</result> <exception-mapping result="fail" exception="java.lang.Exception" /> <interceptor-ref name="defaultStack">
<!-- 必须满足 struts.multipart.maxSize >= fileUpload.maximumSize -->
<param name="fileUpload.maximumSize">20971520</param>
</interceptor-ref> </action> <action name="success/single">
<result>/WEB-INF/pages/upload/success_single.jsp</result>
</action> <action name="fail/single">
<result>/WEB-INF/pages/upload/fail_single.jsp</result>
</action> </package> </struts>

在配置文件中还可以指定解析器,struts 2的上传的与FirstUploadServlet 中的方法一致(servlet3.0之前上传的方式),需要去解析inputstream,strust 2 默认是jakarta解析器,去对inputStream 进行解析。如果超出最大尺寸会抛出异常,可以在action标签中指定局部的异常映射。

5、多文件上传测试案例

index.jsp

<%@ page language = "java" pageEncoding = "UTF-8" %>
<%@ page contentType = "text/html; charset= UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Struts Upload</title>
</head>
<body> <h5>文件上传</h5>
<!-- method 必须是 POST ,enctype 必须是 multipart/form-data -->
<form action="${ pageContext.request.contextPath }/upload/action/single" method="post" enctype="multipart/form-data">
<input type="file" name="upload" >
<input type="submit" value="上传" >
</form> <h5>文件上传</h5>
<!-- method 必须是 POST ,enctype 必须是 multipart/form-data -->
<form action="${ pageContext.request.contextPath }/upload/action/multiple" method="post" enctype="multipart/form-data">
<input type="file" name="upload" >
<br>
<input type="file" name="upload" >
<br>
<input type="file" name="upload" >
<br>
<input type="file" name="upload" >
<br>
<input type="submit" value="上传" >
</form> </body>
</html>

success_single.jsp

<%@ page language = "java" pageEncoding = "UTF-8" %>
<%@ page contentType = "text/html; charset= UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>上传成功</title>
</head>
<body> <h1>上传成功</h1> </body>
</html>

fail_single.jsp

<%@ page language = "java" pageEncoding = "UTF-8" %>
<%@ page contentType = "text/html; charset= UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>上传失败</title>
</head>
<body> <h1>上传失败</h1> </body>
</html>

struts.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd"> <struts> <!-- 允许在 action 的 名称 中使用 / 字符 -->
<constant name="struts.enable.SlashesInActionNames" value="true" />
<!-- 启用动态方法调用 <constant name="struts.enable.DynamicMethodInvocation" value="true" /> --> <!-- 修改 action 请求路径的后缀 -->
<constant name="struts.action.extension" value="do,," />
<!-- 解析器的作用是对request.getInputStream()返回的字节流进行解析获取文件内容、类型、名称(和resultType="stream" 实现下载原理一致) -->
<!-- 指定 对上传的 字节流进行解析的解析器 : jakarta 、cos 、pell -->
<constant name="struts.multipart.parser" value="jakarta" />
<!-- 指定上传文件的尺寸 ( 在 default.properties 中默认定义的大小是 2MB )-->
<constant name="struts.multipart.maxSize" value="2097152000" /> <package name="upload" namespace="/upload" extends="struts-default" > <action name="action/single" class="ecut.upload.SingleFileUploadAction" >
<!-- 通过 param 为 当前的 Action 实例 指定一个参数 ( 实际上是 Action 类中的一个 属性 ) -->
<param name="storePath">D:/</param> <result name="success" type="redirectAction">
<param name="actionName">success/single</param>
</result>
<result name="fail" type="redirectAction">
<param name="actionName">fail/single</param>
</result> <exception-mapping result="fail" exception="java.lang.Exception" /> <interceptor-ref name="defaultStack">
<!-- 必须满足 struts.multipart.maxSize >= fileUpload.maximumSize -->
<param name="fileUpload.maximumSize">20971520</param>
</interceptor-ref> </action> <action name="action/multiple" class="ecut.upload.MultipleFileUploadAction" >
<!-- 通过 param 为 当前的 Action 实例 指定一个参数 ( 实际上是 Action 类中的一个 属性 ) -->
<param name="storePath">D:/</param> <result name="success" type="redirectAction">
<param name="actionName">success/single</param>
</result>
<result name="fail" type="redirectAction">
<param name="actionName">fail/single</param>
</result> <exception-mapping result="fail" exception="java.lang.Exception" /> <interceptor-ref name="defaultStack">
<!-- 必须满足全局上传的文件尺寸最大值 struts.multipart.maxSize >= 单前action上传文件尺寸最大值fileUpload.maximumSize -->
<param name="fileUpload.maximumSize">20971520</param>
</interceptor-ref> </action> <action name="success/single">
<result>/WEB-INF/pages/upload/success_single.jsp</result>
</action> <action name="fail/single">
<result>/WEB-INF/pages/upload/fail_single.jsp</result>
</action> </package> </struts>

Action类

package ecut.upload;

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.List; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import com.opensymphony.xwork2.Action; public class MultipleFileUploadAction implements Action { private static Logger logger = LogManager.getLogger(); private String storePath ; private List<File> upload ;
private List<String> uploadContentType ;
private List<String> uploadFileName ; @Override
public String execute() throws Exception {
logger.info("upload.get(0)对应的类型是uploadContentType.get(0),对应的文件名是uploadFileName.get(0)"); for(int i =0 ; i < upload.size(); i++){
//getCanonicalPath获取规范化路径
Path source = Paths.get( upload.get(i).getCanonicalPath() ); Path target = Paths.get( this.storePath , uploadFileName.get(i) ); //Replace an existing file if it exists.
Files.copy( source , target , StandardCopyOption.REPLACE_EXISTING );
}
return SUCCESS;
} public String getStorePath() {
return storePath;
} public void setStorePath(String storePath) {
this.storePath = storePath;
} public List<File> getUpload() {
return upload;
} public void setUpload(List<File> upload) {
this.upload = upload;
} public List<String> getUploadContentType() {
return uploadContentType;
} public void setUploadContentType(List<String> uploadContentType) {
this.uploadContentType = uploadContentType;
} public List<String> getUploadFileName() {
return uploadFileName;
} public void setUploadFileName(List<String> uploadFileName) {
this.uploadFileName = uploadFileName;
} }

Struts2实现国际化

1、简介

  • 国际化简称i18n,其来源是英文单词 internationalization的首末字符i 和n。18为中间的字符数。
  • 国际化即是对于Web应用来说,页面在不同的语言环境下需要显示不同的效果。
  • Struts2中使用到国际化的地方有: jsp页面的国际化、Action信息国际化、转换错误信息的国际化、校验错误信息的国际化;
  • Struts2国际化文件分类: 全局范围国际化文件 、包范围国际化文件 、Action类范围国际化文件。

2、普通实现表单方式和Struts 2 标签去完成表单比较

<%@ page language = "java" pageEncoding = "UTF-8" %>
<%@ page contentType = "text/html; charset= UTF-8"%>
<%@ taglib prefix = "s" uri = "/struts-tags"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>国际化</title>
<style type="text/css"> .login-form { width: 80% ; margin: 20px auto ; box-shadow: 0px 0px 5px 4px #d3d3d3; padding: 10px 10px ;} .login-form .form-row { height: auto ; overflow: hidden; border-bottom: 1px dotted #d3d3d3 ; padding-bottom: 5px ; }
.login-form .form-row:last-child { border: none ; }
.login-form .form-row i , .login-form .form-row b { height: 30px ; line-height: 30px ; }
.login-form .form-row i { float: left ; width: 30% ; text-align: right ; font-style: normal ; font-size: 18px ; }
.login-form .form-row b { float: right ; width: 70% ; text-align: left ; } .login-form .form-row b input {
margin-left: 1% ; padding-left : 4px ;
height: 20px ; line-height: 20px ; width: 96% ; border: 1px solid #dedede ; outline: none ;
} .login-form .buttons { width: 70% ; margin-left: 30% ; } .login-form .buttons span {
float : left ; width: 50% ; height: 30px ; line-height: 30px ;
} .login-form .buttons span:first-child {
text-align: center ;
} .login-form .buttons span:last-child {
text-align: center ;
} .login-form .buttons span input {
width: 80% ;
}
</style>
</head>
<body> <h3>原生HTML表单</h3> <div class="login-form">
<form action="${ pageContext.request.contextPath }/user/login" method="post" >
<div class="form-row">
<i>用户名:</i>
<b> <input type="text" name="username" ></b>
</div>
<div class="form-row">
<i>密码:</i>
<b> <input type="password" name="password" > </b>
</div>
<div class=" form-row">
<div class="buttons">
<span >
<input type="reset" value="重置">
</span>
<span>
<input type="submit" value="登录">
</span>
</div>
</div>
</form>
</div>
<hr> <h3>Struts 2 表单(不支持国际化)</h3>
<s:form namespace="/user" action="login" method="post" >
<s:textfield label="用户名" name="username" />
<s:password label="密码" name="password" />
<s:reset value="重置" />
<s:submit value="登录" />
</s:form> </body>
</html>

Struts 2实现表单需要先导入标签库,查看Struts 2源码可以得知Struts的表单是用表格实现的,因此两个按钮不在同一行,不太美观,不介意使用Struts实现表单。但是Struts 2实现表单得依赖于Struts 2的标签,因此我们需要先了解Struts 2编写表单。

3、配置文件编写

  • 国际化文件的命名规则

    基本名.properties 如:user_login.properties

    基本名_语言编码_国家编码.properties 如:user_login_en_US.properties, user_login_zh_CN.properties

    其中语言编码和国家编码是固定的,可以在JDK中Locale类的常量中找到。

  • 为了实现程序的国际化,必须先提供程序所需要的资源文件。资源文件的内容基本是key-value对,其中key是程序使用的部分(页面需要和配置文件中一致),而value是程序的显示部分。

user_login_zh_CN.properties

user.login.username.label= User Name
user.login.password.label= Password
user.login.reset.button= Reset
user.login.submit.button= Login

user_login_en_US.properties

user.login.username.label=用户名
user.login.password.label=密码
user.login.reset.button=重置
user.login.submit.button=登录

index.jsp

<%@ page language = "java" pageEncoding = "UTF-8" %>
<%@ page contentType = "text/html; charset= UTF-8"%>
<%@ taglib prefix = "s" uri = "/struts-tags"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>国际化</title>
<style type="text/css"> .login-form { width: 80% ; margin: 20px auto ; box-shadow: 0px 0px 5px 4px #d3d3d3; padding: 10px 10px ;} .login-form .form-row { height: auto ; overflow: hidden; border-bottom: 1px dotted #d3d3d3 ; padding-bottom: 5px ; }
.login-form .form-row:last-child { border: none ; }
.login-form .form-row i , .login-form .form-row b { height: 30px ; line-height: 30px ; }
.login-form .form-row i { float: left ; width: 30% ; text-align: right ; font-style: normal ; font-size: 18px ; }
.login-form .form-row b { float: right ; width: 70% ; text-align: left ; } .login-form .form-row b input {
margin-left: 1% ; padding-left : 4px ;
height: 20px ; line-height: 20px ; width: 96% ; border: 1px solid #dedede ; outline: none ;
} .login-form .buttons { width: 70% ; margin-left: 30% ; } .login-form .buttons span {
float : left ; width: 50% ; height: 30px ; line-height: 30px ;
} .login-form .buttons span:first-child {
text-align: center ;
} .login-form .buttons span:last-child {
text-align: center ;
} .login-form .buttons span input {
width: 80% ;
}
</style>
</head>
<body> <h3>原生HTML表单</h3> <div class="login-form">
<form action="${ pageContext.request.contextPath }/user/login" method="post" >
<div class="form-row">
<i>用户名:</i>
<b> <input type="text" name="username" ></b>
</div>
<div class="form-row">
<i>密码:</i>
<b> <input type="password" name="password" > </b>
</div>
<div class=" form-row">
<div class="buttons">
<span >
<input type="reset" value="重置">
</span>
<span>
<input type="submit" value="登录">
</span>
</div>
</div>
</form>
</div>
<hr> <h3>Struts 2 表单(不支持国际化)</h3>
<s:form namespace="/user" action="login" method="post" >
<s:textfield label="用户名" name="username" />
<s:password label="密码" name="password" />
<s:reset value="重置" />
<s:submit value="登录" />
</s:form> <h3>Struts 2 表单(支持国际化,只有使用Struts标签才可以支持)</h3>
<s:form namespace="/user" action="login" method="post" >
<s:textfield key="user.login.username.label" name="username" />
<s:password key="user.login.password.label" name="password" />
<s:reset key="user.login.reset.button" />
<s:submit key="user.login.submit.button" />
</s:form> <hr>
<!-- 语言代码小写,国家大写 -->
<a href="${ pageContext.request.contextPath }/user/index?request_locale=zh_CN">中文</a>
<a href="${ pageContext.request.contextPath }/user/index?request_locale=en_US">English</a> </body>
</html>

4、struts.xml文件配置

<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd"> <struts> <!-- 指定属性文件的 baseName 就是 除了 "_语言代码_国家或地区代码.properties" 之外的那部分 -->
<constant name="struts.custom.i18n.resources" value="user_login" /> <package name="user" namespace="/user" extends="struts-default" > <action name="index" >
<result>/i18n/index.jsp</result>
</action> <action name="login" ></action> </package>
</struts>

需要参照default.properites ( org/apache/struts2/default.properties,当需要找常量名称时候打开他)增加常量struts.custom.i18n.resources,指定属性文件的 baseName 就是 除了 "_语言代码_国家或地区代码.properties" 之外的那部分

参考博客链接

https://www.cnblogs.com/hellokitty1/p/5083663.html

https://blog.csdn.net/weixin_36380516/article/details/72510292

转载请于明显处标明出处

https://www.cnblogs.com/AmyZheng/p/9230708.html

最新文章

  1. 微信支付(.NET版)
  2. Google之Chromium浏览器源码学习——base公共通用库(三)
  3. Leetcode Reverse Nodes in k-Group
  4. [c#]params可变参数
  5. iOS开发数据库篇—FMDB数据库队列
  6. Hibernate day01笔记
  7. Python.Scrapy.12-scrapy-source-code-analysis-part-2
  8. 【面试题】Google of Greater China Test for New Grads of 2014总结
  9. LoadImage 和 BitBlt
  10. 求前几日的平均值用obj.reduce()方法
  11. Vim自动补全神器:YouCompleteMe(转)
  12. HLS(HTTP Live Streaming)协议之m3u8文件生成方式
  13. 在ubuntu安装Phabricator(转)
  14. 需求收集过程实例之 - GF Phase 1
  15. 有关ArrayList常用方法的源码解析
  16. python爬虫错误总结
  17. 关于tomcat 配置时一闪而过的问题
  18. Java入门(四):运算符优先级、关键字与保留字
  19. emwin 存在多个窗口时,如何获取当前所在窗口
  20. L - The Shortest Path Gym - 101498L (dfs式spfa判断负环)

热门文章

  1. 素问 - 信贷和GDP
  2. 【12】(难&amp;精)【DFS】矩阵中的路径
  3. Jmeter 测试结果分析之聚合报告简介
  4. Java经典面试笔试题及答案
  5. Redis-复制(MasterSlave)
  6. swift中的可选类型
  7. Dirjkstra
  8. Spring_002 依赖注入方式实现
  9. Laravel Vuejs 实战:开发知乎 (2)用户登录
  10. Shiro入门学习之自定义Realm实现认证(四)