指定<form>的method="post", enctype="multipart/form-data"。
accept指定文件类型,有多种类型时逗号分隔,multiple指定可以选择多个文件。
选择的文件是放在请求消息体中的。获取的输入流中包含了上传的所有文件,如果单个上传还好处理,如果同时上传多个,不好从中分离出单个文件的数据,且自己写代码获取文件名很麻烦。
Commons-FileUpload是Apache的开源组件,提供了一套处理上传文件的API。
使用FileUpload需要2个jar包:
commons-fileupload.jar commons-io.jar 这是FileUpload依赖的IO包,要单独下载添加。
FileUpload组件主要的接口、类:
DiskFileItemFactory类 将请求消息实体中的每一个参数都封装为单独的FileItem对象ServletFileUpload类 调用DiskFileItemFactory类来封装请求参数,并对封装好的FileItem做进一步处理,以List<FileItem>形式返回FileItem接口 用于封装请求参数,提供了一系列操作上传文件的方法。
FileItem createItem() //将一个请求参数封装为FileItem,并返回封装好的FileItem。这个方法由DiskFileItemFactory内部自动调用。不用我们管。
set|SizeThreshold(int size) //设置临界值setRepository(File repository) //设置缓存目录。这2个方法都要对应的get方法。
JVM的内存是有限的,比如用户上传一个1G的文件,直接保存在JVM内存中,实打实地占用服务器内存,这绝对不行。
临界值指定文件大小,小于临界值的文件直接存储在JVM内存中,大于临界值的文件,以临时文件(.tmp)的形式保存在缓存目录中。默认为10240,默认单位Byte,即10KB。
缓存目录可以指定为磁盘上的某一个文件夹,以File形式指定,不指定时默认使用系统的临时文件夹。
setFileItemFactory(FileItemFactory fileItemFactory)setSizeMax(long size) //设置请求消息实体内容(传递的所有请求参数)的最大尺寸,防止用户恶意上传超大文件浪费服务器存储空间。默认单位Byte。setFileSizeMax(long size) //设置单个文件的最大尺寸setHeaderEncoding("utf-8") //设置请求参数的字符集,未设置时使用HttpServletRequest设置的字符集,若HttpServletRequest也未设置字符集,则使用系统默认的字符集。
以上几个setter()方法均有对应的getter()方法。
List<FileItem> parseRequest(HttpServletRequest request) //调用FileItemFactory对象的方法,开始封装每个请求参数,以List<FileItem>形式返回封装好的所有的请求参数FileItemIterator getItemIterator(HttpServletRequest request) //同上,只是返回的是迭代器
注意:是封装每一个请求参数,不是只封装上传的文件,所以有些FileItem保存的是普通的请求字段。
void write(File file) //将上传文件写到服务器的磁盘中。如果此文件是存储在缓存目录中的,写完会自动删除缓存目录中对应的临时文件。InputStream getInputStream() //获取输入流void delete() //清除FileItem存储的主体内容,如果存储在缓存目录中,会删除缓存目录中对应的临时文件。虽然GC会自动清除不再使用的临时文件,但使用完立即删除是最好的。
UUID即通用唯一识别码,能唯一标识某个东西。
UUID产生的这个字符串包含32个十六进制数,用4根连词线-分为5段,示例: bd95572b-7fcf-46b2-ae3e-6087d66db40f ,8-4-4-4-12的形式。
最简单的方式:使用<a>标签直接链接到文件地址。
<a href="http://www.xxx.com/resource/特斯拉.mp4">下载xxx</a>有2个问题:
某些类型的文件,比如jpg、mp3、mp4、txt等会直接在网页中打开、播放,而非下载。如果以后资源地址换了,比如换ftp服务器了、改资源路径了,需要一个个地修改<a>连接的href属性,十分麻烦。
解决方式:
(1)链接到Servlet,并传递文件名。
<a href="downloadServlet?fileName=特斯拉.mp4">下载xxx</a>
(2)Servlet
1 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 2 request.setCharacterEncoding("utf-8"); 3 response.setContentType("text/html;charset=utf-8"); 4 5 String fileName = request.getParameter("fileName"); 6 //对文件名进行iso8859-1编码 7 String browerFileName=new String(fileName.getBytes("utf-8"),"iso8859-1"); 8 9 //指定浏览器行为为下载 10 response.addHeader("Content-Type","application/octet-stream"); 11 //指定下载文件名。注意这两个都是addHeader(),不是setHeader() 12 response.addHeader("Content-Disposition","attachment;filename="+browerFileName); 13 14 InputStream is = getServletContext().getResourceAsStream("resource/"+fileName); //换路径时只需修改此句中的路径,不用修改每个<a> 15 ServletOutputStream os= response.getOutputStream(); 16 byte[] buffer = new byte[1024]; 17 int len; 18 while ((len=is.read(buffer))!= -1){ //注意是-1,不是0 19 os.write(buffer); 20 } 21 22 }
红字是为了解决下载文件名中文乱码。
因为我们使用的是utf-8字符集,而chrome这些浏览器默认使用 iso8859-1 字符集。要转换一下,这样浏览器在设置下载文件名时才能识别文件名中的中文。
其实 <a href="downloadServlet?fileName=特斯拉.mp4">下载xxx</a> ,url中的中文也要转换一下,一个中文字符转换为%xxxx的形式(%后面跟着4个十六进制数)。
<a href="downloadServlet?fileName=<%=URLEncoder.encode("特斯拉.mp4","utf-8")%>">下载</a>String URLEncoder.encode(String str, String charset) //静态方法,返回编码后的字符串
当然,不转换也行,都能正确识别。
转载于:https://www.cnblogs.com/chy18883701161/p/11417710.html