文件上传和下载
2019-08-09 / JAVA / 994 次围观 / 0 次吐槽 /文件上传的原理分析
文件上传的前提
Ø 提供form表单,method必须是post
Ø form表单的enctype必须是multipart/form-data
Ø 提供input type="file"类的上传输入域
enctype属性
enctype作用:告知服务器请求正文的MIME类型。(请求消息头:Content-Type作用是一致的)
可选值:
application/x-www-form-urlencoded(默认):
正文:username=admin&password=123
服务器获取数据:String username = request.getParameter("username");
multipart/form-data:
正文:使用IE的开发人员工具来测试
服务器获取数据:request.getParameter(String)方法获取指定的表单字段字符内容,但文件上传表单已经不在是字符内容,而是字节内容,所以失效。
文件上传案例
upload.jsp
<html>
<head>
<title>文件上传</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/UploadServlet" method="post" enctype="multipart/form-data">
用户名:<input type="text" name="username"><br/>
密 码:<input type="password" name="password"><br/>
上 传:<input type="file" name="file"><br/>
<input type="submit" value="提交">
</form>
</body>
</html>
UploadServlet
//获取输入流
InputStream inputStream = request.getInputStream();
//读取
int len = 0;
byte[] bytes = new byte[1024 * 8];
while((len = inputStream.read(bytes)) != -1){
String str = new String(bytes,0,len,"UTF-8");
System.out.println(str);
}
借用第三方解析文件
fileupload概述
Ø fileupload是由apache的commons组件提供的上传组件。它最主要的工作就是帮我们解析request.getInputStream()。
Ø 使用fileupload只需要2个jar包
fileupload的核心类有:
DiskFileItemFactory、ServletFileUpload、FileItem
解析原理
FileItem对象介绍
Ø FileItem对象对应一个表单项(表单字段)。可以是文件字段或普通字段
Ø boolean isFormField():判断当前表单字段是否为普通文本字段,如果返回false,说明是文件字段;
Ø String getFieldName():获取字段名称,例如:<input type=”text” name=”username”/>,返回的是username;
Ø String getString():获取字段的内容,如果是文件字段,那么获取的是文件内容,当然上传的文件必须是文本文件;
Ø String getName():获取文件字段的文件名称;(a.txt)
Ø String getContentType():获取上传的文件的MIME类型,例如:text/plain。
Ø int getSize():获取上传文件的大小;
Ø InputStream getInputStream():获取上传文件对应的输入流;
Ø void write(File):把上传的文件保存到指定文件中。
Ø delete():删除临时文件
使用fileupload实现文件上传代码
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取表单文件数据
DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();//创建工厂对象
ServletFileUpload upload = new ServletFileUpload(diskFileItemFactory);//创建文件上传对象
try {
List<FileItem> items = upload.parseRequest(request);//获取FileItem/标签数据
for (FileItem item : items){
if(item.isFormField()){//普通数据
System.out.println(item.getFieldName() + "--" + item.getString("UTF-8"));
}else{//文件数据
//取当前日期
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
String date = simpleDateFormat.format(new Date());
String path = request.getServletContext().getRealPath("upload\\" + date);//保存路径
//创建文件夹
File dir = new File(path);
if (!dir.exists()){//不存在
dir.mkdirs();
}
//保存
String suffix = item.getName().split("\\.")[item.getName().split("\\.").length - 1];//后缀
String name = UUID.randomUUID().toString() + "." + suffix;//文件名
String dirPath = path + "\\" + name;
try {
item.write(new File(dirPath));
item.delete();//删除临时文件
} catch (Exception e) {
e.printStackTrace();
}
}
}
} catch (FileUploadException e) {
e.printStackTrace();
}
}
文件上传保存路径的几种方案
方案一:添加日期目录,方便分类查找
方式二:把日期20180108转成16进制字符串d12fde2f
文件上传应该注意的问题
中文乱码问题
表单普通字段乱码用item.getString("UTF-8");
文件名乱码可用
文件上传大小限制问题
单个文件大小:
ServletFileUpload.setFileSizeMax(字节)
总文件大小:(多文件上传)
ServletFileUpload.setSizeMax(字节)
临时文件的问题
Ø DiskFileItemFactory:
作用:产生FileItem对象
内部有一个缓存,缓存大小默认是10Kb。如果上传的文件超过10Kb,用磁盘作为缓存。
存放缓存文件的目录在哪里?默认是系统的临时目录。
如果自己用IO流实现的文件上传,要在流关闭后,清理临时文件。调用FileItem.delete();
多文件上传
文件下载
文件下载需要设置响应头
Content-Disposition
attachment;filename=xx.png | 以附件形式下载 |
Content-Type
application/octet-stream | 二进制流 |
案例下载代码
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取文件信息
String fileName = request.getParameter("file");
String fileDate = request.getParameter("date");
//组合文件路径
String filePath = request.getServletContext().getRealPath("upload\\" + fileDate) + "\\" + fileName;
//发送文件
File file = new File(filePath);
if(file.exists()){
//设置请求头
fileName = URLEncoder.encode(fileName,"UTF-8");//文件名设置UTF-8编码
response.setHeader("Content-disposition","attachment;filename=" + fileName);
response.setContentType("application/octet-stream");//以二进制的数据返回客户端
FileInputStream fileInputStream = new FileInputStream(file);
byte[] buf = new byte[1024 * 8];//缓冲区
ServletOutputStream outputStream = response.getOutputStream();
int len = 0;
while((len = fileInputStream.read(buf)) != -1){
outputStream.write(buf,0,len);
}
fileInputStream.close();
outputStream.close();
}else{
response.setHeader("content-type","text/html;charset=UTF-8");
response.getWriter().write("文件不存在");
}
}
- 上一篇:使用过滤器解决get&post请求中文乱码
- 下一篇:java中的注解
Powered By Cheug's Blog
Copyright Cheug Rights Reserved.