JavaWeb之文件上传、下载
时间:2016-12-17 18:07
——文件上传概述
上传不能使用BaseServlet
1、文件上传的作用
例如网络硬盘,就是用来上传和下载文件的。
2、文件上传对表单的限制
1)必须使用表单,而不能是超链接
2)表单的method必须是POST,而不能是GET
3)表单的enctype必须是multipart/form-data
4)在表单中添加type="file",即<input type="file" name="" />
<form action="xxx" method="post" enctype="multipart/form-data">
用户名:<input type="text" name="username" /><br/>
照 片:<input type="file" name="photo" /><br/>
<input type="submit" value="上传" />
</form>
3、文件上传对Servlet的限制
1)当表单为enctype="multipart/form-data"时,不能使用request.getParameter()方法,该方法永远返回null。
2)使用ServletInputStream request.getInputStream()来获取完整的请求体。
4、多部件表单结构
1)分割出多个部件,即一个表单项生成一个部件。
2)一个部件中会自己包含请求头和空行以及请求体。
3)普通表单项:
> 一个头:
* Content-Disposition,包含name="xxx",即表单项名称。
> 体就是表单项的值。
4)文件表单项:
> 两个头:
* Content-Disposition,包含name="xxx",即表单项名称,还有一个filename="xxx",表示上传文件的名称。
* Content-Type:它是上传文件的MIME类型,例如:image/jpeg,表示上传的是图片。
> 体就是上传文件的内容。
——commons-fileupload
* commins-fileupload.jar
* 依赖包:commons-io.jar
这个组件会解析request中的上传数据,解析后的结果是一个表单项数据封装到一个FileItem对象中,只需要调用FIleItem对象的方法即可。(多个表单项会封装多个FileItem,即List<FileItem>)
1、上传三个步骤
相关类:
* 工厂类:DiskFileItemFactory
* 解析器:ServletFileUpload
* 表单项:FileItem(该类对应一个表单项)
1)创建工厂:
DiskFileItemFactory factory = new DiskFileItemFactory();
2)创建解析器:
ServletFileUpload sfu = new ServletFileUpload(factory);
3)使用解析器来解析request,得到FileItem集合:
List<FileItem> fileItemList = sfu.parseRequest(request);
2、FileItem类
普通表单项相关方法:
* boolean isFormField()
是否为普通表单项。
true为普通表单项。
false为文件表单项。
* String getFieldName()
返回当前表单项的名称。
* String getString(String charset)
通过指定编码获取表单项的值。
该方法不适用于文件表单项。
必须指定编码。
文件表单项相关方法:
* String getName()
返回上传的文件名称。
* long getSize()
返回上传文件的字节数。
* String getContentType()
获取MIME类型。
* InputStream getInputStream()
返回上传文件对应的输入流。
* void write(File file)
将上传的文件写入指定文件中。
如果file已存在,则会替换目标文件,如果file不存在,则会创建该文件。
——文件上传简单示例
===============================================================================
com.wyc.servlet.UploadServlet
System.out.println("文件大小:" + size);
------------------------------------------------------------------------------------------------------------------------------
form.jsp
===============================================================================
——文件上传细节
1、把上传的文件放到WEB-INF目录下
如果没有把用户上传的文件放到WEB-INF目录下,那么用户就可以通过浏览器直接访问上传的文件,这是非常危险的。
假如说用户上传了一个JSP文件,然后用户再通过浏览器去访问这个JSP文件,那么服务器就会执行JSP文件中的内容,如果在JSP文件中有如下语句:Runtime.getRuntime().exec("shutdown -s -t 1");.........
通常我们会在WEB-INF目录下创建一个upload目录来存放上传的文件,而在Servlet中找到这个目录需要使用ServletContext()的getRealPath(String)方法,例如在项目中有如下语句:
ServletContext servletContext = this.getServletContext();
String uploadPath = servletContext.getRealPath("/WEB-INF/uploads");
其中uploadPath为:G:\tomcat\webapps\FileDemo\WEB-INF\uploads
2、文件名称(完整路径)
上传的文件名称可能是完整路径。
IE6获取的上传文件名称是完整路径,而在其他浏览器获取的上传文件名称只是文件名称而已,浏览器差异的问题还需要处理一下。
例如:C:\file\哈哈.jpg
可以通过分割字符串来获取文件名。
int index = fileName.lastIndexOf("\\");
if(index != -1)
fileName = fileName.substring(index+1);
3、处理文件名称乱码和普通表单项乱码
当上传的文件名称中包含中文时,需要设置编码,commons-fileupload组件为我们提供了两种设置编码的方式:
request.setCharacterEncoding("utf-8");
fileUpload.setHeaderEncoding(String charset); // 这种方式的优先级高于前一种。
commons-fileupload内部会调用request.getCharacterEncoding();来指定编码。
上传文件的文件内容中包含中文:
通常我们不需要关心上传文件的内容,因为我们会把上传文件保存到硬盘上,也就是说,原文件是什么样子,保存到服务器之后还是什么样子。
如果想要在控制台显示上传文件的内容,那么可以使用fileItem.getString(String encoding)来使用指定编码处理字符串。
文本内容和普通表单项内容都是用FileItem类的getString(String encoding)来处理编码。
4、文件重名问题
应该为每个文件名添加前缀名称,这个前缀要保证不能重复,可以使用UUID。
fileName = CommonUtils.getUuid() + "_" + fileName;
===============================================================================
5、一个目录不能存放过多文件(存放目录打散)
一个目录下不应该存放过多的文件,一般一个目录存放1000个文件就是上限了,如果再多,那么打开目录时就会很“卡”。
也就是说,我们需要把上传的文件存放到不同的目录中,但是也不能为每个上传的文件都新建一个目录,这样会导致目录过多,所以我们应该采用某种算法来“打散”存放文件的目录。
方法有很多,例如使用日期来打散,每天生成一个目录,也可以使用文件名的首字母来生成目录,相同首字母的文件放到同一目录下。
日期打散算法:如果某一天上传的文件过多,那么也会出现一个目录文件过多的情况。
首字母打散算法:
例如abc.txt,那么可以把文件保存到a目录下,如果a目录不存在,则创建a目录。
如果文件名是中文的,因为中文过多,所以会导致目录过多的情况。
哈希打散算法:
* 通过文件名称得到一个int值,即调用hashCode()获取哈希值。
* 将int值转换成16进制。
* 获取16进制的前两位用来生成目录,目录为两层:例如1B2C3D4E5F,使用/1/B/ 来保存文件。
该存储方式非常不直观,一般会将文件存放的目录保存起来,以后访问下载时可以直接获取。
===============================================================================
6、上传的单个文件、整个表单的大小限制
限制上传文件的大小很简单,ServletFileUpload类的setFileSizeMax(long)就可以实现了,参数就是上传文件的上限字节数,例如:servletFileUpload.setFileSizeMax(1024 * 10),表示上限为10kb。
该方法一定要在parseRequest()方法之前调用。
一旦上传的文件大小超出了上限,那么就会在执行parseRequest()方法时抛出FileUploadBase.FileSizeLimitExceededException异常。
我们可以在Servlet中获取这个异常,然后想页面输出“上传的文件大小超出限制”。
限制整个表单的大小:
fileUpload.setSizeMax(long size);
该方法必须在parseRequest()方法之前调用。
如果大小超出限制,会抛出FileUploadBase.SizeLimitExceededException异常。
===============================================================================
7、设置缓存大小与临时目录
* 缓存大小:
默认为10kb,当上传文件超出缓存大小时,先将文件保存到硬盘,当文件上传完毕后,再将文件保存。
* 临时目录:
缓存的保存目录。
* 可以通过DiskFileItemFactory的构造方法来指定缓存大小和临时目录
DiskFileItemFactory(int sizeThreshold, File repository)
> 默认的临时目录为:System.getProperty("java.io.tmpdir");,打印后:G:\apache-tomcat-7.0.72\temp
> 例如:new DiskFileItemFactory(1024 * 10, new File("F:/temp"));
// 打印默认临时目录
===============================================================================
——文件下载
被下载的资源必须放到WEB-INF目录下,然后通过Servlet完成下载。
在JSP页面中给出超链接,链接到DownloadServlet,并提供要下载的文件名称,然后在DownloadServlet获取文件的真实路径,然后把文件写入到response.getOutputStream()流中。
1、概述
下载就是向客户端响应字节数据。
之前响应的都是HTML的字符数据。
其实就是把一个文件编程字节数组,使用response.getOutputStream()来将文件响应给浏览器。
2、下载的要求
两个头、一个流
* Content-Type:表示传递给客户端文件的MIME类型。
> 通过文件名称调用ServletContext的getMimeType()方法得到MIME类型。
* Content-Disposition:
> 它的默认值为inline,表示在浏览器窗口中打开(当打不开时会弹框)。
> attachment;filename=xxx:表示类型为附件,并在弹框的界面中显示下载的文件名。
* 流:要下载的文件数据。
> 自己new 一个输入流即可,然后通过IOUtils完成流的数据写入。
——下载示例
——DownloadUtils(下载文件名乱码问题)
显示在下载框中包含中文名称时,会出现乱码。
* FireFox,使用Base64编码。
* 其他大部分浏览器,使用URL编码。
通用方法:filename = new String(filename.getBytes("gbk"), "iso-8859-1");
浏览器能读懂ISO-8859-1编码
public static String fileNameEncoding(String fileName, HttpServletRequest request) throws Exception{
注意:
Base64Encoder并不属于JDK标准库范畴,但是又包含在了JDK中,解决方法:
1、按照如下方法设置Eclipse导入%JAVA_HOME%\jre\lib目录下的rt.jar包即可,Project->Properties,选择Java Build Path设置项,再选择Libraries标签,Add External Jars添加%JAVA_HOME%\jre\lib\rt.jar就可以使用了。
2、MyEclipse —— Preferences —— Java —— Compiler —— Errors/Warnings —— Deprecated and restricted API —— Forbidden reference(access rules): Ignore
——BASE64Encoder、BASE64Decoder
JavaWeb之文件上传、下载的更多相关文章
- JavaWeb实现文件上传下载功能实例解析
转:http://www.cnblogs.com/xdp-gacl/p/4200090.html JavaWeb实现文件上传下载功能实例解析 在Web应用系统开发中,文件上传和下载功能是非常常用的功能 ...
- JavaWeb实现文件上传下载功能实例解析 (好用)
转: JavaWeb实现文件上传下载功能实例解析 转:http://www.cnblogs.com/xdp-gacl/p/4200090.html JavaWeb实现文件上传下载功能实例解析 在Web ...
- Javaweb学习笔记——上传下载文件
一.前言 在Javaweb中,上传下载是经常用到的功能,对于文件上传,浏览器在上传的过程中是以流的过程将文件传给服务器,一般都是使用commons-fileupload这个包实现上传功能,因为comm ...
- JavaWeb 文件 上传 下载
文件上传下载对于一个网站来说,重要性不言而喻.今天来分享一个JavaWeb方式实现的文件上传下载的小例子. 项目依赖 项目目录 工作流程 文件上传 表单处的设置 服务器端 上传功能的实现 upload ...
- JavaWeb多文件上传及zip打包下载
项目中经常会使用到文件上传及下载的功能.本篇文章总结场景在JavaWeb环境下,多文件上传及批量打包下载功能,包括前台及后台部分. 首先明确一点: 无法通过页面的无刷新ajax请求,直接发下载.上 ...
- JavaWeb:实现文件上传与下载
JavaWeb:实现文件上传与下载 文件上传前端处理 本模块使用到的前端Ajax库为Axio,其地址为GitHub官网. 关于文件上传 上传文件就是把客户端的文件发送给服务器端. 在常见情况(不包含文 ...
- JavaWeb 文件上传下载
1. 文件上传下载概述 1.1. 什么是文件上传下载 所谓文件上传下载就是将本地文件上传到服务器端,从服务器端下载文件到本地的过程.例如目前网站需要上传头像.上传下载图片或网盘等功能都是利用文件上传下 ...
- JavaWeb -- 文件上传下载示例
1. 上传简单示例 Jsp <%@ page language="java" import="java.util.*" pageEncoding=&quo ...
- 转载:JavaWeb 文件上传下载
转自:https://www.cnblogs.com/aaron911/p/7797877.html 1. 文件上传下载概述 1.1. 什么是文件上传下载 所谓文件上传下载就是将本地文件上传到服务器端 ...
- JavaWeb:实现文件上传
JavaWeb:实现文件上传 理解文件上传: 1.上传文件就是把客户端的文件发送给服务器端. 2.HTTP响应的正文部分最常见的是HTML文档,但是也可以是其他任意格式的数据,如图片和声音文件中的数据 ...
随机推荐
- python + Excel数据读取(更新)
data.xlsx 数据如下: import xlrd#1.读取Excel数据# table = xlrd.open_workbook("data.xlsx","r&qu ...
- LC-322. 零钱兑换
322. 零钱兑换 给你一个整数数组 coins ,表示不同面额的硬币:以及一个整数 amount ,表示总金额. 计算并返回可以凑成总金额所需的 最少的硬币个数 .如果没有任何一种硬币组合能组成总金 ...
- mac上安装brew----笔记
一.mac 终端下,执行以下命令,即可安装brew: 介绍brew:是Mac下的一款包管理工具brew [brew install 软件],类似与centos里面的 yum[yum install 软 ...
- elementUI的el-input和el-select宽度 一致
在用vue时,用到了element组件的 el-input 和 el-select(多选框)组件,但是宽度显示不一样,查看了多选框的css,发现element-style是写死的 添加style=&q ...
- 初探Node-red结合阿里云数据库,定时显示数据
在最近的项目中,隔壁项目组推荐了一个很好的基于node.js开源IOT框架Node-Red,它的优点很明显,使用可视化编程的方式,实现了大部分需要在物联网领域的技术,而且能很好的对接各个云平台,快捷部 ...
- djinn靶机
仅供个人娱乐 靶机信息 https://download.vulnhub.com/djinn/djinn.ova 一.主机探测 二.漏洞的查找和利用 21端口ftp 匿名登录 7331端口 命令执行 ...
- shell $? 状态码含义
Linux 使用了$? 来保存上个执行的命令的退出状态码. 0 命令成功结束 1 通用未知错误 2 误用she ...
- 【网站公告】避免反对百度的限制措施:百度搜索过来的访问会自动禁用js权限
今天下午百度联系我们,发现通过百度搜索访问我们网站的博文时会出现下面反对百度的画面,让我们今天彻底处理好,保证不再出现这种情况. 我们排查后发现是这位博主申请了js权限,添加了下面的反对百度的脚本: ...
- 【NLP学习其五】模型保存与载入的注意事项(记问题No module named 'model')
这是一次由于路径问题(找不到模型)引出模型保存问题的记录 最近,我试着把使用GPU训练完成的模型部署至预发布环境时出现了一个错误,以下是log节选 unpickler.load() ModuleNot ...
- .NET Core/.NET5/.NET6 开源项目汇总13:模板引擎
系列目录 [已更新最新开发文章,点击查看详细] 开源项目是众多组织与个人分享的组件或项目,作者付出的心血我们是无法体会的,所以首先大家要心存感激.尊重.请严格遵守每个项目的开源协议后再使用.尊 ...