文件上传和下载
2019-08-09 / JAVA / 922 次围观 / 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.