文件上传的原理

我们以前学习上传的时候知道需要将表单的enctype属性设置为multipart/form-data. 表单的enctype属性指定的是表单数据的编码方式,有三个值: -application/x-www-form-urlencoded:这是默认的编码方式。只处理表单的value属性值。采用这种会将表单域的值处理为url编码方式。 -multipart/form-data:这种编码方式会以二进制流的方式来处理表单数据,会将文件域里指定文件内容也封装到请求参数里。 -text/plain:这种方式主要用于直接通过表单发送邮件的情况。

我们用一个简单的案例来说明一下application/x-www-form-urlencoded 和multipart/form-data的区别。

案例:上传表单

        <body>
<form action="${pageContext.request.contextPath }/DemoServlet" enctype="application/x-www-form-urlencoded" method="post">
上传文件:<input type="file" name="file"><br>
请求参数:<input type="text" name="username"><br>
<input type="submit" value="提交" name="dd">
</form>
</body>

处理Servlet,这里的处理直接通过二进制流来处理http请求。这是底层的方式,当通过request的getParameter方法获取请求参数时,实际上是web服务器替我们处理了这种底层的二进制流,并转换成对应的请求参数值。

            public class DemoServlet extends HttpServlet {

                protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
InputStream is=request.getInputStream();
BufferedReader br=new BufferedReader(new InputStreamReader(is));
String buffer=null;
while((buffer=br.readLine())!=null)
{
System.out.println(buffer);
}
} }
    然后我们访问页面,选中file.txt文件 输入框中输入张三 ,点击提交
输出
file=file.txt&username=%E5%BC%A0%E4%B8%89&dd=%E6%8F%90%E4%BA%A4 这个字符串包含了三个属性,file,username 和 dd
浏览器会将表单里所有具有name属性的表单项转换成请求参数,因为提交按钮也有name属性,因此也被转换成请求参数。 这里的编码都是使用url编码。可以通过java提供的URLDecoder解码。
大部分时候,程序中通过getParameter方法即可获得参数,底层的二进制流处理,以及使用URLDecoder处理请求参数,都由web服务器帮我们完成了,。
显然,通过上面这种方式,只能获取到文件名,不能获取到文件的内容,所以为了实现文件上传,只能将enctype属性设置为multipart/form-data.
一旦设置了表单的 enctype属性设置为multipart/form-data getParameter方法就无法使用。 当我们设置完以后,再次点击提交,则输出 ------WebKitFormBoundary2lDSbdeEx3KW1Tup
Content-Disposition: form-data; name="file"; filename="file.txt"
Content-Type: text/plain 我是上传文件
------WebKitFormBoundary2lDSbdeEx3KW1Tup
Content-Disposition: form-data; name="username" zhangsan
------WebKitFormBoundary2lDSbdeEx3KW1Tup-- 这时我们发现文件的内容也获取到,我们只需要通过io流的知识将其分割然后获取指定的参数即可。
对于一个成熟的文件上传框架,需要完成的逻辑很简单,分析request请求的二进制流,解析出数据,然后允许开发者以简单的方式获取数据内容即可。 Servlet3.0给我们所提供了提供了更加简单的文件上传方法,我们可以查阅API进行使用,这里不再细说。

Struts2的文件上传

struts2并未提供自己的上传组件。在struts.properties配置文件中,可以看到底层配置的是Common-fileupload组件。

但struts在原有的组件上进行了封装,因此底层的上传组件可以随意切换,代码不用变化

(1)编写我们的Action动作类

            public class UploadAction extends ActionSupport {
private String username;
private File upload; //封装了文件内容,无法获得文件名和文件类型
private String uploadContentType;//封装了文件类型,xxxContentType
private String uploadFileName; //用xxxFileName封装文件名字 public String getUsername() {
return username;
} public void setUsername(String username) {
this.username = username;
} 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;
} public String upload(){
//获取真实路径
String savepath=ServletActionContext.getRequest().getRealPath("/WEB-INF/files");
File file=new File(savepath);
//判断文件是否存在,不存在就创建相应的目录等
if(!file.exists()){
file.mkdirs();
}
//将上传的临时文件重命名并且另存到指定地址
upload.renameTo(new File(file,uploadFileName));
return null;
} }

 (2)配置Action

            <package name="p1" extends="struts-default">
<action name="upload" class="com.cad.struts2.action.UploadAction" method="upload">
</action>
</package>

文件过滤

            我们可以自己手动判断文件大小,文件类型来进行文件过滤,但是比较繁琐。
struts2为我们提供了一个fileUpload拦截器,来帮我们实现文件过滤。
fileUpload拦截器也被配置在了默认的拦截器栈中 fileUpload拦截器有两个参数
-allowedTypes:该参数指定允许上传的文件类型,多个文件类型之间用逗号分割,
-maximumSize:该属性指定允许上传的文件大小,单位是字节
struts2默认的允许上传文件大小为2MB。 设置最大允许上传文件大小为30M ,经过测试,这种方法行不通,不知道具体原因是什么。
<action name="upload" class="com.cad.struts2.action.UploadAction" method="upload">
<interceptor-ref name="defaultStack">
<param name="fileUpload.allowedTypes">image/jpg</param>
<param name="fileUpload.maximumSize">31457280</param>
</interceptor-ref>
</action> 所以我们只能通过配置常量来修改允许上传文件的大小
<constant name="struts.multipart.maxSize" value="31457280"></constant>

  

同时上传多个文件

        需要将文件表单项的name设置成相同的。

            表单页面
<body>
<form action="${pageContext.request.contextPath }/upload.action" enctype="multipart/form-data" method="post">
上传文件1:<input type="file" name="upload"><br>
上传文件2:<input type="file" name="upload"><br>
上传文件3:<input type="file" name="upload"><br>
用户名:<input type="text" name="username"><br>
<input type="submit" value="提交">
</form>
</body>
            然后写Action类,需要将file,fileName,ContentType等用数组封装起来
然后遍历得到
public class UploadAction extends ActionSupport {
private String username;
private File upload[];
private String uploadContentType[];
private String uploadFileName[]; public String getUsername() {
return username;
} public void setUsername(String username) {
this.username = username;
} 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;
} public String upload(){
String savepath=ServletActionContext.getRequest().getRealPath("/WEB-INF/files");
File file=new File(savepath);
if(!file.exists()){
file.mkdirs();
}
for(int i=0;i<upload.length;i++){
upload[i].renameTo(new File(file,uploadFileName[i]));
}
return null;
} }

Struts2的文件下载

    创建下载的action类 

                public class DownloadAction extends ActionSupport {
private InputStream input; public InputStream getInput() {
return input;
} public void setInput(InputStream input) {
this.input = input;
} public String download() throws Exception{
//获取文件路径
String path=ServletActionContext.getRequest().getRealPath("/WEB-INF/files/photo.jpg");
//读取文件
input=new FileInputStream(path);
return SUCCESS;
}
}

 

    配置Action
struts2指定了stream结果类型,专门用来处理下载。 contentType:被下载文件的文件类型。
contentDisposition:下载文件弹窗,文件名等
inputName:action类中流的名字 <action name="download" class="com.cad.struts2.action.DownloadAction" method="download">
<result name="success" type="stream">
<param name="contentType">application/octet-stream</param>
<param name="contentDisposition">attachment;filename=phpto.jpg</param>
<param name="inputName">input</param>
</result>
</action>

  

 

 

  

  

 

  

  

  

  

(十五)struts2的文件上传和下载的更多相关文章

  1. struts2实现文件上传和下载

    在做B/S系统时,通常会涉及到上传文件和下载文件,在没接struts2框架之前,我们都是使用apache下面的commons子项目的FileUpload组件来进行文件的上传,但是那样做的话,代码看起来 ...

  2. Struts2的文件上传与下载

    <一>简述: Struts2的文件上传其实也是通过拦截器来实现的,只是该拦截器定义为默认拦截器了,所以不用自己去手工配置,<interceptor name="fileUp ...

  3. 【Struts2】文件上传与下载

    一.上传 1.1 Struts2实现步骤 浏览器端 服务器端 1.2 关于Struts2中文件上传细节: 1.3 示例 jsp文件 Action类 struts.xml文件配置 二.下载 2.1 文件 ...

  4. Struts2之文件上传与下载

    时间:2017-1-11 15:47 --使用commons-fileupload组件上传1.客户端    *   method="post"    *   <input t ...

  5. Struts2实现文件上传和下载,多文件上传,限制文件大小,限制文件类型

    文件上传使用的包:commons-upload-xx.jar                                 commons-io-xx.jar 一.实现文件上传: 1.在表单空间中添 ...

  6. 11、Struts2 的文件上传和下载

    文件上传 表单准备 要想使用 HTML 表单上传一个或多个文件 须把 HTML 表单的 enctype 属性设置为 multipart/form-data 须把 HTML 表单的method 属性设置 ...

  7. Struts2入门(七)——Struts2的文件上传和下载

    一.前言 在之前的随笔之中,我们已经了解Java通过上传组件来实现上传和下载,这次我们来了解Struts2的上传和下载. 注意:文件上传时,我们需要将表单提交方式设置为"POST" ...

  8. Struts2 实现文件上传和下载

    实现上传功能 Struts2实际上是使用的commons fileupload 组件,所以记得导包哦. 1.首先你应该有一个上传页面 <!-- file的name属性与action中的File类 ...

  9. 7、Struts2实现文件上传和下载

    一.实现单个文件上传 1.创建如下web项目结构 2.在src下的com.action包下创建UploadAction.java package com.action; import java.io. ...

随机推荐

  1. 2021 NGK新机遇!---NGK生态所、星空计划双赛道爆发

    2021年数字加密货币行业迎来几大发展机遇:1.比特币为首的数量加密资产正处于另类资产向数字黄金定位的历史性巨大发展机遇中,2.Defi等新项目异军提起,形成丰富的行业生态,将在未来对旧有的金融格局产 ...

  2. 使用docker mediawiki,搭建网页wiki

    我只是想做一个大家都能访问的wiki,用于成员间共享和维护一些文档.找到了docker的mediawiki,这里记录一下我怎么搭的吧. 首先,如果你在一个局域网里,有公用的可以访问的服务器,那可以直接 ...

  3. 系统错误,MSVCP100D.dll找不到或丢失!

    文章首发 | 公众号:lunvey 今日研究c++,找了一些示例程序,发现无法打开.弹出如下的报错提示: 作为新时代人类,遇见问题第一件事情就是问度娘.然而眼花缭乱的检索数据,大家众说纷纭,不知道如何 ...

  4. Vue为何采用异步渲染

    Vue为何采用异步渲染 Vue在更新DOM时是异步执行的,只要侦听到数据变化,Vue将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更,如果同一个watcher被多次触发,只会被推入到队列中一次 ...

  5. 新手不能忽视的MFC编程之CString

    首发文章 | 公众号:lunvey 作为一个新手,刚接触C++没多久.赶鸭子上架完成项目,鉴于之前有几年编程基础,所以很快就接触到了界面开发,由于用的是VC++6.0,所以自然而然就将MFC作为图形界 ...

  6. A study on ILC for linear discrete systems with single delay

    论文题目就是随笔的题目,以后的随笔的命名都是如此,特此说明. 论文的主要内容是偏理论研究的,引入了离散矩阵延迟指数函数,来处理具有单时滞线性离散系统.对于离散延迟矩阵指数函数其定义为: \[e_{m} ...

  7. 安装并运行Nacos

    方式一:源码或者安装包 一.下载源码或者安装包 git clone https://github.com/alibaba/nacos.git 二.安装 cd nacos/ mvn -Prelease- ...

  8. Js和JQuery基础

    1.JavaScript的组成 CMAScript (核心):规定了JS的语法和基本对象 DOM 文档对象模型:处理网页内容的方法和接口 BOM 浏览器对象模型:与浏览器交互的方法和接口 2.Java ...

  9. ctf.show_web13(文件上传之.user.ini)

    这是一道文件上传题,先二话不说丢个图片码,显示为 先考虑文件太小,用burp抓包,添加了一堆无用的东西后显示仍然是error file zise,直到上传正常图片依旧如此,考虑文件太大.将一句话木马修 ...

  10. MarkDown简单语法回顾

    写在前面: 本文是我的第一篇博客文章,希望与大家共同交流.分享我们热爱的技术,努力成为一名优秀的软件工程师! 进入正文 使用MarkDown记笔记已经有些时候了,编辑器是使用的sublime text ...