Java Web基础知识之文件上传:文件上传一窥究竟
其实文件上传的文章已经写得很多了,但是好多文章都是都是说明了怎么实现,没有说这个过程到底发生了什么(会不会引来仇恨。。),其实实现文件上传并不复杂,也没有多少代码,但是要是清楚的明白其中的原理还是费点功夫的,这里就还原文件上传的整个过程。
其实关于文件上传在最早之前是使用Apache的Commons FileUpload组件,但是自从servlet提出了自己的解决办法之后,就不再使用这个组件了,有了正规军谁还使用民兵啊,不对,也不一定,之前Apache的HttpClient就比JDK自己的HttpUrlConnection流行,不说废话了,直接进入!
一、 客户端编程
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>File upload</title>
</head>
<body><form action="/JavaServlet/fileUploadServlet" method="post" enctype="multipart/form-data">select a file :<input type="file" name="file" multiple><input type="text" value="upload file" name="identifier" /><input type="submit" value="upload" /></form>
</body>
</html>
关于这个页面有几点值得注意:
- 首先是action是URI,注意它和URL的区别,不要省掉contextPath,这样会找不到该资源的;
- enctype的值一定是multipart/form-data,这个属性是指在发送放到服务器之前如何对表单数据进行编码,这种方式是将表单数据组装成一条消息,并用分隔符将表单的每个部分分隔开;默认值是application/x-www-form-urlencoded,也意味着所有的值都会进行编码,这种方式是用键值对来进行编码;
- 如果想要上传多个文件,可以使用multiple属性,注意这个属性是在HTML5中提出的,这样就不用我们使用多个input来上传多个文件了;
下面我上传三个文件,可以看到Http请求和响应如下,我使用的是chrome浏览器:
二、 服务端编程
- 在一个由multipart/form-data组成的请求中,每一个部分包括非文件部分都会转换成一个Part对象,在服务器端我们主要是针对该Part对象进行处理;
- 通过查看Part中是否存在content-type首部来判断一个Part是属于普通的非文件部分,还是属于文件部分;
- 如果存在content-type,则说明文件部分存在,之后查看上传的文件名称是否为空,文件名为空说明有客户端没有选择要上传的文件;
- 如果文件存在,就使用Part的write方法来将他写入服务器端的文件系统;
@WebServlet(name="fileUploadServlet", urlPatterns={"/fileUploadServlet"})
//@MultipartConfig(location="/")
@MultipartConfig
public class FileUploadServlet extends HttpServlet {private static final long serialVersionUID = 1920423365061691218L;@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {Collection<Part> parts = req.getParts();for(Part part: parts){if(part.getContentType() != null){String filename = getFileName(part);if(filename != null && !filename.isEmpty()){part.write(filename);}} }}String getFileName(Part part){Objects.requireNonNull(part, "part can not be null");String disposition = part.getHeader("content-disposition");String[] disParts = disposition.split(";");String filenamePart = disParts[disParts.length - 1];String filename = filenamePart.substring(filenamePart.indexOf("=")+1).trim().replace("\"", "");return filename;}
}
关于上述的处理其实主要围绕@MultipartConfig注解和Part接口来进行,关于这两个的使用其实很简单,可以查看一下JavaDoc即可,但是有两个我要着重说一下,因为我自己就掉坑里了:
- 一个就是@MultipartConfig中的location属性,这个绝对是一个坑,当这个值是一个绝对路径时,调用Part的write()方法将该文件写到对应的路径是没有问题的,但是当是相对路径的时候,比如如我上边写的"/",这个相对路径是相对于tomcat路径下的C:\Program Files\tomcat7\work\Catalina\localhost\JavaServlet路径的,这是一个文件上传临时保存的位置,这个路径值主要是为了在文件超过预设大小时写入硬盘,为@MultiSizeThreshold准备,所以最好还是不要使用这个属性为好;
- 还有一个就是Part中的getName()方法并不是用来获取文件名的,而是用来获取表单元素中的name属性的;文件名需要我们自己来解析出来;
- 在使用Part的write()方法时,如果提供的是相对路径,那么相对路径的根路径都是C:\Program Files\tomcat7\work\Catalina\localhost\JavaServlet;
三、 其他问题
- 对文件的后缀名进行验证和约束;
- 对文件的大小进行约束;
- 文件的存储,是放在本地文件系统上还是数据库中;
- 文件的编码问题,尤其是中文的编码问题;
- 避免相同文件名的文件的重复上传导致覆盖问题;
- 表单提交时编码类型enctype详解
- Returning Values from Forms: multipart/form-data
- Tomcat根目录下work文件夹的作用
- The @MultipartConfig Annotation
- Java web-文件上传
- What's the difference between “Request Payload” vs “Form Data” as seen in Chrome dev tools Network tab
Java Web基础知识之文件上传:文件上传一窥究竟相关推荐
- java WEB 基础复习_开篇--Java Web基础知识
本篇主要是博客的开篇,是一些很基础的知识,我写博客的目的很简单.主要是供自己学习使用,督促自己学习,希望自己能坚持下来. 当前三大主流的Web动态网页技术是PHP(Personal Home Page ...
- Java Web基础知识之安全:人生苦短,注意安全
关于web程序中的安全方面,想必大多数人都不甚了解,或者说感觉没有必要了解,身边开发网站的人主要就是注重后台的功能和前台的界面,不要说程序的安全问题,甚至后台数据库访问的问题可能都没有下大力气解决.但 ...
- java培训基础知识都学哪些
很多人都开始学习java技术,觉得java语言在未来的发展前景空间非常大,事实却是如此,那么针对于零基础的同学, 学习java技术需要学哪些呢?下面我们就来看看java培训基础知识都学哪些? java ...
- Java面试基础知识III
Java面试基础知识: 1.C++或Java中的异常处理机制的简单原理和应用. 当JAVA 程序违反了JAVA的语义规则时,JAVA虚拟机就会将发生的错误表示为一个异常.违反语义规则包括2种情况.一种 ...
- Java Web基础
目录 Java Web基础 HTML基础 HTML补充 CSS基础 CSS补充 JavaScript基础 JavaScript补充(例题) Java Web补充 Java Web基础 HTML基础 标 ...
- 【笔记】网易微专业-Web安全工程师-01.WEB基础知识
课程概述: 本课是基础中的基础,通俗易懂的讲解了Web的本质和Web开发的基础知识.对于Web小白,建议从头开始抓紧学习:对于已经有一定Web基础知识的同学,建议快速的过一遍,夯实基础. 课程大纲: ...
- Java进阶基础知识
Java进阶基础知识 1.Java 基础 Java类设计的原则就是内聚性,一致性和封装性是Java设计的基本原则 1.1 Java基础理论 Java基础理论知识 1.2继承的优缺点 1.2.1优点 : ...
- 你觉得什么才是 Java 的基础知识?
近日里,很多人邀请我回答各种j2ee开发的初级问题,我无一都强调java初学者要先扎实自己的基础知识,那什么才是java的基础知识?又怎么样才算掌握了java的基础知识呢?这个问题还真值得仔细思考. ...
- java ee基础知识_Java EE:基础知识
java ee基础知识 想要了解一些基本原则,即与Java EE相关的技术术语. 对于许多人来说,Java EE / J2EE仍然最多意味着Servlet,JSP或Struts. 没有冒犯或双关语! ...
- hashcode是什么意思_什么才是 Java 的基础知识?
作者:晓风轻 链接:zhuanlan.zhihu.com/p/28615617 近日里,很多人邀请我回答各种j2ee开发的初级问题,我无一都强调java初学者要先扎实自己的基础知识,那什么才是java ...
最新文章
- IPS与IDS部署场景(直路部署,单臂部署,旁路部署,阻断)
- 套娃的开始——Network in Network网络学习笔记
- mac上的命令行工具
- 运行maven项目整合ssm时的错误笔记
- 计算机六级好考吗,计算机六级考什么?
- 牛客网暑期ACM多校训练营(第三场): A. Ternary String(欧拉降幂+递推)
- Nacos概述,下载与安装,初始化配置,服务注册应用,RestTemplate,Feign
- vip会员统计表 (vip等级是灵活配置的 非写死1是金卡用户 2是什么 等)
- cognos ibm 收购_IBM Cognos与Linux上的Sterling Selling and Fulfillment Suite集成
- 为什么说Mobileye最辉煌的5年就是落后的5年
- zune自搭虚拟服务器离线升级,Zune 30g 购买/使用 个人经验贴,希望可以帮到有需要的烧友~...
- 服务器重装Linux系统详细图文教程(centos7)
- LNK1104:无法打开文件d3dx11.lib
- 华大460 GPIO 例程赏析_20220911
- 基于javaagent-ByteBuddy监控方法执行耗时
- Oracle 分组数据
- C# 读取txt文件生成Word文档
- [LeetCode]Medium - Cutting Ribbons - python
- nc文件的读取与可视化-python
- Arduino 无源蜂鸣器警报声
热门文章
- 辞旧迎新又一年(18年年终总结)
- HTML两张图片翻转,canvas实现图片镜像翻转的2种方式
- R语言详解参数检验和非参数检验——样本T检验、方差分析、pearson相关性检验、单样本wilcoxon检验、Mann-Whitney检验、配对样本wilcoxon检验、列联表检验、卡方检验
- 关于LaTex输入大写罗马字母的命令——\expandafter的理解与\MakeUppercase的使用
- 五分钟告诉你什么是爬虫?
- Python与爬虫有什么关系?
- linux 屏幕录像软件,Linux_Linux下好用的5个屏幕录像软件,在很多时候,我们需要将在 Lin - phpStudy...
- 系统自带恶意软件清理助手
- 【酷毙了】野火新版fireTools多功能调试助手,有Windows和Linux版本,就问你喜不喜欢。...
- Clonezilla再生龙备份系统分区详细教程