首页 文章资讯内容详情

java文件上传和下载

2026-06-01 4 花语

本文内容纲要:

简介

****文件上传和下载是javaweb中常见的操作,文件上传主要是将文件通过IO流传放到服务器的某一个特定的文件夹下,而文件下载则是与文件上传相反,将文件从服务器的特定的文件夹下的文件通过IO流下载到本地。

对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用Servlet获取上传文件的输入流然后再解析里面的请求参数是比较麻烦,所以一般选择采用apache的开源工具common-fileupload这个文件上传组件。这个common-fileupload上传组件的jar包可以去apache官网上面下载,也可以在struts的lib文件夹下面找到,struts上传的功能就是基于这个实现的。common-fileupload是依赖于common-io这个包的,所以还需要下载这个包。

文件上传

1、文件上传页面和消息提示页面

upload.jsp页面的代码如下:

1<%@pagelanguage="java"pageEncoding="UTF-8"%> 2<!DOCTYPEHTML> 3<html> 4<head> 5<title>文件上传</title> 6</head> 7 8<body> 9<formaction="${pageContext.request.contextPath}/servlet/uploadHandleServlet2"enctype="multipart/form-data"method="post"上传用户:<inputtype="text"name="username"><br/> 10上传文件1:<inputtype="file"name="file1"><br/> 11上传文件2:<inputtype="file"name="file2"><br/> 12<inputtype="submit"value="提交"> 13</form> 14</body> 15</html>

在文件上传的页面要用enctype="multipart/form-data"method="post"来表示进行文件上传。

2、处理文件上传的Servlet

1publicclassUploadHandleServletextendsHttpServlet{ 2 3@Override 4protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{ 5//得到上传文件的保存目录,将上传的文件存放于WEB-INF目录下,不允许外界直接访问,保证上传文件的安全 6StringsavePath=this.getServletContext().getRealPath("/WEB-INF/upload"); 7Filefile=newFile(savePath); 8if(!file.exists()&&!file.isDirectory()){ 9System.out.println("目录或文件不存在!"); 10file.mkdir(); 11} 12//消息提示 13Stringmessage=""; 14try{ 15//使用Apache文件上传组件处理文件上传步骤: 16//1、创建一个DiskFileItemFactory工厂 17DiskFileItemFactorydiskFileItemFactory=newDiskFileItemFactory(); 18//2、创建一个文件上传解析器 19ServletFileUploadfileUpload=newServletFileUpload(diskFileItemFactory); 20//解决上传文件名的中文乱码 21fileUpload.setHeaderEncoding("UTF-8"); 22//3、判断提交上来的数据是否是上传表单的数据 23if(!fileUpload.isMultipartContent(request)){ 24//按照传统方式获取数据 25return; 26} 27//4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项 28List<FileItem>list=fileUpload.parseRequest(request); 29for(FileItemitem:list){ 30//如果fileitem中封装的是普通输入项的数据 31if(item.isFormField()){ 32Stringname=item.getFieldName(); 33//解决普通输入项的数据的中文乱码问题 34Stringvalue=item.getString("UTF-8"); 35Stringvalue1=newString(name.getBytes("iso8859-1"),"UTF-8"); 36System.out.println(name+""+value); 37System.out.println(name+""+value1); 38}else{ 39//如果fileitem中封装的是上传文件,得到上传的文件名称, 40StringfileName=item.getName(); 41System.out.println(fileName); 42if(fileName==null||fileName.trim().equals("")){ 43continue; 44} 45//注意:不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如:c:\a\b\1.txt,而有些只是单纯的文件名,如:1.txt 46//处理获取到的上传文件的文件名的路径部分,只保留文件名部分 47fileName=fileName.substring(fileName.lastIndexOf(File.separator)+1); 48//获取item中的上传文件的输入流 49InputStreamis=item.getInputStream(); 50//创建一个文件输出流 51FileOutputStreamfos=newFileOutputStream(savePath+File.separator+fileName); 52//创建一个缓冲区 53bytebuffer[]=newbyte[1024]; 54//判断输入流中的数据是否已经读完的标识 55intlength=0; 56//循环将输入流读入到缓冲区当中,(len=in.read(buffer))>0就表示in里面还有数据 57while((length=is.read(buffer))>0){ 58//使用FileOutputStream输出流将缓冲区的数据写入到指定的目录(savePath+"\\"+filename)当中 59fos.write(buffer,0,length); 60} 61//关闭输入流 62is.close(); 63//关闭输出流 64fos.close(); 65//删除处理文件上传时生成的临时文件 66item.delete(); 67message="文件上传成功"; 68} 69} 70}catch(FileUploadExceptione){ 71//TODOAuto-generatedcatchblock 72e.printStackTrace(); 73message="文件上传失败"; 74} 75request.setAttribute("message",message); 76request.getRequestDispatcher("/message.jsp").forward(request,response); 77} 78 79@Override 80protectedvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{ 81doGet(request,response); 82} 83 84}

3、文件上传的细节

上述的代码虽然可以成功将文件上传到服务器上面的指定目录当中,但是文件上传功能有许多需要注意的小细节问题,以下列出的几点需要特别注意的:

(1)、为保证服务器安全,上传文件应该放在外界无法直接访问的目录下,比如放于WEB-INF目录下。

(2)、为防止文件覆盖的现象发生,要为上传文件产生一个唯一的文件名。

(3)、为防止一个目录下面出现太多文件,要使用hash算法打散存储。

(4)、要限制上传文件的最大值。

(5)、要限制上传文件的类型,在收到上传文件名时,判断后缀名是否合法。

4、改进后的servlet

1publicclassUploadHandleServlet1extendsHttpServlet{ 2 3@Override 4protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{ 5//得到上传文件的保存目录,将上传的文件存放于WEB-INF目录下,不允许外界直接访问,保证上传文件的安全 6StringsavePath=this.getServletContext().getRealPath("/WEB-INF/upload"); 7//上传时生成的临时文件保存目录 8StringtempPath=this.getServletContext().getRealPath("/WEB-INF/temp"); 9Filefile=newFile(tempPath); 10if(!file.exists()&&!file.isDirectory()){ 11System.out.println("目录或文件不存在!"); 12file.mkdir(); 13} 14//消息提示 15Stringmessage=""; 16try{ 17//使用Apache文件上传组件处理文件上传步骤: 18//1、创建一个DiskFileItemFactory工厂 19DiskFileItemFactorydiskFileItemFactory=newDiskFileItemFactory(); 20//设置工厂的缓冲区的大小,当上传的文件大小超过缓冲区的大小时,就会生成一个临时文件存放到指定的临时目录当中。 21diskFileItemFactory.setSizeThreshold(1024*100); 22//设置上传时生成的临时文件的保存目录 23diskFileItemFactory.setRepository(file); 24//2、创建一个文件上传解析器 25ServletFileUploadfileUpload=newServletFileUpload(diskFileItemFactory); 26//解决上传文件名的中文乱码 27fileUpload.setHeaderEncoding("UTF-8"); 28//监听文件上传进度 29fileUpload.setProgressListener(newProgressListener(){ 30publicvoidupdate(longpBytesRead,longpContentLength,intarg2){ 31System.out.println("文件大小为:"+pContentLength+",当前已处理:"+pBytesRead); 32} 33}); 34//3、判断提交上来的数据是否是上传表单的数据 35if(!fileUpload.isMultipartContent(request)){ 36//按照传统方式获取数据 37return; 38} 39//设置上传单个文件的大小的最大值,目前是设置为1024*1024字节,也就是1MB 40fileUpload.setFileSizeMax(1024*1024); 41//设置上传文件总量的最大值,最大值=同时上传的多个文件的大小的最大值的和,目前设置为10MB 42fileUpload.setSizeMax(1024*1024*10); 43//4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项 44List<FileItem>list=fileUpload.parseRequest(request); 45for(FileItemitem:list){ 46//如果fileitem中封装的是普通输入项的数据 47if(item.isFormField()){ 48Stringname=item.getFieldName(); 49//解决普通输入项的数据的中文乱码问题 50Stringvalue=item.getString("UTF-8"); 51Stringvalue1=newString(name.getBytes("iso8859-1"),"UTF-8"); 52System.out.println(name+""+value); 53System.out.println(name+""+value1); 54}else{ 55//如果fileitem中封装的是上传文件,得到上传的文件名称, 56StringfileName=item.getName(); 57System.out.println(fileName); 58if(fileName==null||fileName.trim().equals("")){ 59continue; 60} 61//注意:不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如:c:\a\b\1.txt,而有些只是单纯的文件名,如:1.txt 62//处理获取到的上传文件的文件名的路径部分,只保留文件名部分 63fileName=fileName.substring(fileName.lastIndexOf(File.separator)+1); 64//得到上传文件的扩展名 65StringfileExtName=fileName.substring(fileName.lastIndexOf(".")+1); 66if("zip".equals(fileExtName)||"rar".equals(fileExtName)||"tar".equals(fileExtName)||"jar".equals(fileExtName)){ 67request.setAttribute("message","上传文件的类型不符合!!!"); 68request.getRequestDispatcher("/message.jsp").forward(request,response); 69return; 70} 71//如果需要限制上传的文件类型,那么可以通过文件的扩展名来判断上传的文件类型是否合法 72System.out.println("上传文件的扩展名为:"+fileExtName); 73//获取item中的上传文件的输入流 74InputStreamis=item.getInputStream(); 75//得到文件保存的名称 76fileName=mkFileName(fileName); 77//得到文件保存的路径 78StringsavePathStr=mkFilePath(savePath,fileName); 79System.out.println("保存路径为:"+savePathStr); 80//创建一个文件输出流 81FileOutputStreamfos=newFileOutputStream(savePathStr+File.separator+fileName); 82//创建一个缓冲区 83bytebuffer[]=newbyte[1024]; 84//判断输入流中的数据是否已经读完的标识 85intlength=0; 86//循环将输入流读入到缓冲区当中,(len=in.read(buffer))>0就表示in里面还有数据 87while((length=is.read(buffer))>0){ 88//使用FileOutputStream输出流将缓冲区的数据写入到指定的目录(savePath+"\\"+filename)当中 89fos.write(buffer,0,length); 90} 91//关闭输入流 92is.close(); 93//关闭输出流 94fos.close(); 95//删除处理文件上传时生成的临时文件 96item.delete(); 97message="文件上传成功"; 98} 99} 100}catch(FileUploadBase.FileSizeLimitExceededExceptione){ 101e.printStackTrace(); 102request.setAttribute("message","单个文件超出最大值!!!"); 103request.getRequestDispatcher("/message.jsp").forward(request,response); 104return; 105}catch(FileUploadBase.SizeLimitExceededExceptione){ 106e.printStackTrace(); 107request.setAttribute("message","上传文件的总的大小超出限制的最大值!!!"); 108request.getRequestDispatcher("/message.jsp").forward(request,response); 109return; 110}catch(FileUploadExceptione){ 111//TODOAuto-generatedcatchblock 112e.printStackTrace(); 113message="文件上传失败"; 114} 115request.setAttribute("message",message); 116request.getRequestDispatcher("/message.jsp").forward(request,response); 117} 118 119@Override 120protectedvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{ 121doGet(request,response); 122} 123//生成上传文件的文件名,文件名以:uuid+"_"+文件的原始名称 124publicStringmkFileName(StringfileName){ 125returnUUID.randomUUID().toString()+"_"+fileName; 126} 127publicStringmkFilePath(StringsavePath,StringfileName){ 128//得到文件名的hashCode的值,得到的就是filename这个字符串对象在内存中的地址 129inthashcode=fileName.hashCode(); 130intdir1=hashcode&0xf; 131intdir2=(hashcode&0xf0)>>4; 132//构造新的保存目录 133Stringdir=savePath+"\\"+dir1+"\\"+dir2; 134//File既可以代表文件也可以代表目录 135Filefile=newFile(dir); 136if(!file.exists()){ 137file.mkdirs(); 138} 139returndir; 140} 141}

5、如果在文件上传中IO流成为了系统的性能瓶颈,可以考虑使用NIO来提高性能。改进servlet代码如下:

1publicclassUploadHandleServlet2extendsHttpServlet{ 2 3@Override 4protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{ 5//得到上传文件的保存目录,将上传的文件存放于WEB-INF目录下,不允许外界直接访问,保证上传文件的安全 6StringsavePath=this.getServletContext().getRealPath("/WEB-INF/upload"); 7//上传时生成的临时文件保存目录 8StringtempPath=this.getServletContext().getRealPath("/WEB-INF/temp"); 9Filefile=newFile(tempPath); 10if(!file.exists()&&!file.isDirectory()){ 11System.out.println("目录或文件不存在!"); 12file.mkdir(); 13} 14//消息提示 15Stringmessage=""; 16try{ 17//使用Apache文件上传组件处理文件上传步骤: 18//1、创建一个DiskFileItemFactory工厂 19DiskFileItemFactorydiskFileItemFactory=newDiskFileItemFactory(); 20//设置工厂的缓冲区的大小,当上传的文件大小超过缓冲区的大小时,就会生成一个临时文件存放到指定的临时目录当中。 21diskFileItemFactory.setSizeThreshold(1024*100); 22//设置上传时生成的临时文件的保存目录 23diskFileItemFactory.setRepository(file); 24//2、创建一个文件上传解析器 25ServletFileUploadfileUpload=newServletFileUpload(diskFileItemFactory); 26//解决上传文件名的中文乱码 27fileUpload.setHeaderEncoding("UTF-8"); 28//监听文件上传进度 29fileUpload.setProgressListener(newProgressListener(){ 30publicvoidupdate(longpBytesRead,longpContentLength,intarg2){ 31System.out.println("文件大小为:"+pContentLength+",当前已处理:"+pBytesRead); 32} 33}); 34//3、判断提交上来的数据是否是上传表单的数据 35if(!fileUpload.isMultipartContent(request)){ 36//按照传统方式获取数据 37return; 38} 39//设置上传单个文件的大小的最大值,目前是设置为1024*1024字节,也就是1MB 40fileUpload.setFileSizeMax(1024*1024); 41//设置上传文件总量的最大值,最大值=同时上传的多个文件的大小的最大值的和,目前设置为10MB 42fileUpload.setSizeMax(1024*1024*10); 43//4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项 44List<FileItem>list=fileUpload.parseRequest(request); 45for(FileItemitem:list){ 46//如果fileitem中封装的是普通输入项的数据 47if(item.isFormField()){ 48Stringname=item.getFieldName(); 49//解决普通输入项的数据的中文乱码问题 50Stringvalue=item.getString("UTF-8"); 51Stringvalue1=newString(name.getBytes("iso8859-1"),"UTF-8"); 52System.out.println(name+""+value); 53System.out.println(name+""+value1); 54}else{ 55//如果fileitem中封装的是上传文件,得到上传的文件名称, 56StringfileName=item.getName(); 57System.out.println(fileName); 58if(fileName==null||fileName.trim().equals("")){ 59continue; 60} 61//注意:不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如:c:\a\b\1.txt,而有些只是单纯的文件名,如:1.txt 62//处理获取到的上传文件的文件名的路径部分,只保留文件名部分 63fileName=fileName.substring(fileName.lastIndexOf(File.separator)+1); 64//得到上传文件的扩展名 65StringfileExtName=fileName.substring(fileName.lastIndexOf(".")+1); 66if("zip".equals(fileExtName)||"rar".equals(fileExtName)||"tar".equals(fileExtName)||"jar".equals(fileExtName)){ 67request.setAttribute("message","上传文件的类型不符合!!!"); 68request.getRequestDispatcher("/message.jsp").forward(request,response); 69return; 70} 71//如果需要限制上传的文件类型,那么可以通过文件的扩展名来判断上传的文件类型是否合法 72System.out.println("上传文件的扩展名为:"+fileExtName); 73//获取item中的上传文件的输入流 74InputStreamfis=item.getInputStream(); 75//得到文件保存的名称 76fileName=mkFileName(fileName); 77//得到文件保存的路径 78StringsavePathStr=mkFilePath(savePath,fileName); 79System.out.println("保存路径为:"+savePathStr); 80//创建一个文件输出流 81FileOutputStreamfos=newFileOutputStream(savePathStr+File.separator+fileName); 82//获取读通道 83FileChannelreadChannel=((FileInputStream)fis).getChannel(); 84//获取读通道 85FileChannelwriteChannel=fos.getChannel(); 86//创建一个缓冲区 87ByteBufferbuffer=ByteBuffer.allocate(1024); 88//判断输入流中的数据是否已经读完的标识 89intlength=0; 90//循环将输入流读入到缓冲区当中,(len=in.read(buffer))>0就表示in里面还有数据 91while(true){ 92buffer.clear(); 93intlen=readChannel.read(buffer);//读入数据 94if(len<0){ 95break;//读取完毕 96} 97buffer.flip(); 98writeChannel.write(buffer);//写入数据 99} 100//关闭输入流 101fis.close(); 102//关闭输出流 103fos.close(); 104//删除处理文件上传时生成的临时文件 105item.delete(); 106message="文件上传成功"; 107} 108} 109}catch(FileUploadBase.FileSizeLimitExceededExceptione){ 110e.printStackTrace(); 111request.setAttribute("message","单个文件超出最大值!!!"); 112request.getRequestDispatcher("/message.jsp").forward(request,response); 113return; 114}catch(FileUploadBase.SizeLimitExceededExceptione){ 115e.printStackTrace(); 116request.setAttribute("message","上传文件的总的大小超出限制的最大值!!!"); 117request.getRequestDispatcher("/message.jsp").forward(request,response); 118return; 119}catch(FileUploadExceptione){ 120//TODOAuto-generatedcatchblock 121e.printStackTrace(); 122message="文件上传失败"; 123} 124request.setAttribute("message",message); 125request.getRequestDispatcher("/message.jsp").forward(request,response); 126} 127 128@Override 129protectedvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{ 130doGet(request,response); 131} 132//生成上传文件的文件名,文件名以:uuid+"_"+文件的原始名称 133publicStringmkFileName(StringfileName){ 134returnUUID.randomUUID().toString()+"_"+fileName; 135} 136publicStringmkFilePath(StringsavePath,StringfileName){ 137//得到文件名的hashCode的值,得到的就是filename这个字符串对象在内存中的地址 138inthashcode=fileName.hashCode(); 139intdir1=hashcode&0xf; 140intdir2=(hashcode&0xf0)>>4; 141//构造新的保存目录 142Stringdir=savePath+"\\"+dir1+"\\"+dir2; 143//File既可以代表文件也可以代表目录 144Filefile=newFile(dir); 145if(!file.exists()){ 146file.mkdirs(); 147} 148returndir; 149} 150} 文件下载

****1、列出提供下载的文件资源

要将Web应用系统中的文件资源提供给用户进行下载,首先我们要有一个页面列出上传文件目录下的所有文件,当用户点击文件下载超链接时就进行下载操作,编写一个ListFileServlet,用于列出Web应用系统中所有下载文件。

ListFileServlet代码如下:

1publicclassListFileServletextendsHttpServlet{ 2@Override 3protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{ 4doPost(request,response); 5} 6@Override 7protectedvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{ 8//TODOAuto-generatedmethodstub 9//获取上传文件的目录 10StringuploadFilePath=this.getServletContext().getRealPath("/WEB-INF/upload"); 11//存储要下载的文件名 12Map<String,String>fileMap=newHashMap<String,String>(); 13//递归遍历filepath目录下的所有文件和目录,将文件的文件名存储到map集合中 14fileList(newFile(uploadFilePath),fileMap); 15//将Map集合发送到listfile.jsp页面进行显示 16request.setAttribute("fileMap",fileMap); 17request.getRequestDispatcher("/listfile.jsp").forward(request,response); 18 19} 20//递归遍历指定目录下的所有文件 21publicvoidfileList(Filefile,MapfileMap){ 22//如果file代表的不是一个文件,而是一个目录 23if(!file.isFile()){ 24//列出该目录下的所有文件和目录 25File[]files=file.listFiles(); 26//遍历files[]数组 27for(Filefile2:files){ 28System.out.println(file2.getName()); 29//递归 30fileList(file2,fileMap); 31} 32}else{ 33/*处理文件名,上传后的文件是以uuid_文件名的形式去重新命名的,去除文件名的uuid_部分 34file.getName().indexOf("_")检索字符串中第一次出现"_"字符的位置,如果文件名类似于:9349249849-88343-8344_阿_凡_达.avi 35那么file.getName().substring(file.getName().indexOf("_")+1)处理之后就可以得到阿_凡_达.avi部分 36*/ 37StringrealName=file.getName().substring(file.getName().lastIndexOf("_")+1); 38//file.getName()得到的是文件的原始名称,这个名称是唯一的,因此可以作为key,realName是处理过后的名称,有可能会重复 39fileMap.put(file.getName(),realName); 40} 41} 42}

说明一下,一般文件路径在数据库中保存,然后再数据库中查询结果在页面显示。

listfile.jsp页面

1<%@pagelanguage="java"import="java.util.*"pageEncoding="UTF-8"%> 2<%@taglibprefix="c"uri="http://java.sun.com/jsp/jstl/core"%> 3<!DOCTYPEHTML> 4<html> 5<head> 6<title>下载文件显示页面</title> 7</head> 8 9<body> 10<!--遍历Map集合--> 11<c:forEachvar="me"items="${fileMap}"> 12<c:urlvalue="/servlet/downLoadServlet"var="downurl"> 13<c:paramname="filename"value="${me.key}"></c:param> 14</c:url> 15${me.value}<ahref="${downurl}">下载</a> 16<br/> 17</c:forEach> 18</body> 19</html>

2、文件下载

DownLoadServlet的代码如下:

1publicclassDownLoadServletextendsHttpServlet{ 2 3@Override 4protectedvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{ 5//得到要下载的文件名 6StringfileName=request.getParameter("filename"); 7fileName=newString(fileName.getBytes("iso8859-1"),"UTF-8"); 8//上传的文件都是保存在/WEB-INF/upload目录下的子目录当中 9StringfileSaveRootPath=this.getServletContext().getRealPath("/WEB-INF/upload"); 10//处理文件名 11Stringrealname=fileName.substring(fileName.indexOf("_")+1); 12//通过文件名找出文件的所在目录 13Stringpath=findFileSavePathByFileName(fileName,fileSaveRootPath); 14//得到要下载的文件 15Filefile=newFile(path+File.separator+fileName); 16//如果文件不存在 17if(!file.exists()){ 18request.setAttribute("message","您要下载的资源已被删除!!"); 19request.getRequestDispatcher("/message.jsp").forward(request,response); 20return; 21} 22 23//设置响应头,控制浏览器下载该文件 24response.setHeader("content-disposition","attachment;filename="+URLEncoder.encode(realname,"UTF-8")); 25//读取要下载的文件,保存到文件输入流 26FileInputStreamfis=newFileInputStream(path+File.separator+fileName); 27//创建输出流 28OutputStreamfos=response.getOutputStream(); 29//设置缓存区 30ByteBufferbuffer=ByteBuffer.allocate(1024); 31//输入通道 32FileChannelreadChannel=fis.getChannel(); 33//输出通道 34FileChannelwriteChannel=((FileOutputStream)fos).getChannel(); 35while(true){ 36buffer.clear(); 37intlen=readChannel.read(buffer);//读入数据 38if(len<0){ 39break;//传输结束 40} 41buffer.flip(); 42writeChannel.write(buffer);//写入数据 43} 44//关闭输入流 45fis.close(); 46//关闭输出流 47fos.close(); 48} 49 50@Override 51protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{ 52doPost(request,response); 53} 54//通过文件名和存储上传文件根目录找出要下载的文件的所在路径 55publicStringfindFileSavePathByFileName(StringfileName,StringfileSaveRootPath){ 56inthashcode=fileName.hashCode(); 57intdir1=hashcode&0xf; 58intdir2=(hashcode&0xf0)>>4; 59Stringdir=fileSaveRootPath+"\\"+dir1+"\\"+dir2; 60Filefile=newFile(dir); 61if(!file.exists()){ 62file.mkdirs(); 63} 64returndir; 65} 66}

3、如果IO成为系统的瓶颈,可以考虑使用NIO来实现下载,提供系统性能,改进后的DownloadServlet代码如下:

1publicclassDownLoadServlet1extendsHttpServlet{ 2 3@Override 4protectedvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{ 5//得到要下载的文件名 6StringfileName=request.getParameter("filename"); 7fileName=newString(fileName.getBytes("iso8859-1"),"UTF-8"); 8//上传的文件都是保存在/WEB-INF/upload目录下的子目录当中 9StringfileSaveRootPath=this.getServletContext().getRealPath("/WEB-INF/upload"); 10//处理文件名 11Stringrealname=fileName.substring(fileName.indexOf("_")+1); 12//通过文件名找出文件的所在目录 13Stringpath=findFileSavePathByFileName(fileName,fileSaveRootPath); 14//得到要下载的文件 15Filefile=newFile(path+File.separator+fileName); 16//如果文件不存在 17if(!file.exists()){ 18request.setAttribute("message","您要下载的资源已被删除!!"); 19request.getRequestDispatcher("/message.jsp").forward(request,response); 20return; 21} 22 23//设置响应头,控制浏览器下载该文件 24response.setHeader("content-disposition","attachment;filename="+URLEncoder.encode(realname,"UTF-8")); 25//读取要下载的文件,保存到文件输入流 26FileInputStreamin=newFileInputStream(path+File.separator+fileName); 27//创建输出流 28OutputStreamos=response.getOutputStream(); 29//设置缓存区 30byte[]bytes=newbyte[1024]; 31intlen=0; 32while((len=in.read(bytes))>0){ 33os.write(bytes); 34} 35//关闭输入流 36in.close(); 37//关闭输出流 38os.close(); 39} 40 41@Override 42protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{ 43doPost(request,response); 44} 45//通过文件名和存储上传文件根目录找出要下载的文件的所在路径 46publicStringfindFileSavePathByFileName(StringfileName,StringfileSaveRootPath){ 47inthashcode=fileName.hashCode(); 48intdir1=hashcode&0xf; 49intdir2=(hashcode&0xf0)>>4; 50Stringdir=fileSaveRootPath+"\\"+dir1+"\\"+dir2; 51Filefile=newFile(dir); 52if(!file.exists()){ 53file.mkdirs(); 54} 55returndir; 56} 57}

参考博客:http://www.cnblogs.com/xdp-gacl/p/4200090.html

本文内容总结:

原文链接:https://www.cnblogs.com/lcngu/p/5471610.html