RESPONSE IO流的方式下载,大文件如何处理,求教!

问题描述

代码如下:publicvoiddownFILE(Stringdest,OutputStreamos){FileInputStreamfis=null;try{fis=newFileInputStream(dest);byte[]buffer=newbyte[4096];intn;while((n=fis.read(buffer,0,buffer.length))!=-1){os.write(buffer,0,n);}}catch(Exceptione){}finally{try{fis.close();os.flush();os.close();}catch(IOExceptione){}}}上面入参分别是:dest:本地硬盘的一个ZIP文件(大小为2G)OS:为WEB请求的返回,response.getOutStream();请教一下CSDN的大神们,我有点疑问:上面是WEB页面中,用户点击一个导出链接后执行的后台文件流下载方法,如果是小文件没关系,大文件的话如何处理?现在这样的写法,大文件就直接报内存溢出的错误!再就是上面的缓冲区是不是失去意义了(如果是本地硬盘文件之间的IO,肯定有效果)这里通过WEB方式下载,缓冲区的概念是不是没用了?求大神们指点小弟一下,谢谢了!

解决方案

解决方案二:
用RandomAccessFile试试,参考下这个:packagecom.defonds.cds.common;importjava.io.BufferedOutputStream;importjava.io.File;importjava.io.IOException;importjava.io.OutputStream;importjava.io.RandomAccessFile;importjavax.servlet.ServletException;importjavax.servlet.http.HttpServlet;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;importorg.apache.commons.logging.Log;importorg.apache.commons.logging.LogFactory;importcom.defonds.cds.common.util.CommonUtil;//HTTP断点续传demo(客户端测试工具:快车、迅雷)publicclassArcSyncHttpDownloadServletextendsHttpServlet{privatestaticfinallongserialVersionUID=1L;finalstaticLoglog=LogFactory.getLog(ArcSyncHttpDownloadServlet.class);@OverrideprotectedvoiddoGet(HttpServletRequestreq,HttpServletResponseresp)throwsServletException,IOException{this.doPost(req,resp);}@OverrideprotectedvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse){FiledownloadFile=newFile("D:/defonds/book/pattern/SteveJobsZH.pdf");//要下载的文件longfileLength=downloadFile.length();//记录文件大小longpastLength=0;//记录已下载文件大小intrangeSwitch=0;//0:从头开始的全文下载;1:从某字节开始的下载(bytes=27000-);2:从某字节开始到某字节结束的下载(bytes=27000-39000)longtoLength=0;//记录客户端需要下载的字节段的最后一个字节偏移量(比如bytes=27000-39000,则这个值是为39000)longcontentLength=0;//客户端请求的字节总量StringrangeBytes="";//记录客户端传来的形如“bytes=27000-”或者“bytes=27000-39000”的内容RandomAccessFileraf=null;//负责读取数据OutputStreamos=null;//写出数据OutputStreamout=null;//缓冲byteb[]=newbyte[1024];//暂存容器if(request.getHeader("Range")!=null){//客户端请求的下载的文件块的开始字节response.setStatus(javax.servlet.http.HttpServletResponse.SC_PARTIAL_CONTENT);log.info("request.getHeader("Range")="+request.getHeader("Range"));rangeBytes=request.getHeader("Range").replaceAll("bytes=","");if(rangeBytes.indexOf('-')==rangeBytes.length()-1){//bytes=969998336-rangeSwitch=1;rangeBytes=rangeBytes.substring(0,rangeBytes.indexOf('-'));pastLength=Long.parseLong(rangeBytes.trim());contentLength=fileLength-pastLength+1;//客户端请求的是969998336之后的字节}else{//bytes=1275856879-1275877358rangeSwitch=2;Stringtemp0=rangeBytes.substring(0,rangeBytes.indexOf('-'));Stringtemp2=rangeBytes.substring(rangeBytes.indexOf('-')+1,rangeBytes.length());pastLength=Long.parseLong(temp0.trim());//bytes=1275856879-1275877358,从第1275856879个字节开始下载toLength=Long.parseLong(temp2);//bytes=1275856879-1275877358,到第1275877358个字节结束contentLength=toLength-pastLength+1;//客户端请求的是1275856879-1275877358之间的字节}}else{//从开始进行下载contentLength=fileLength;//客户端要求全文下载}/***如果设设置了Content-Length,则客户端会自动进行多线程下载。如果不希望支持多线程,则不要设置这个参数。*响应的格式是:*Content-Length:[文件的总大小]-[客户端请求的下载的文件块的开始字节]*ServletActionContext.getResponse().setHeader("Content-Length",*newLong(file.length()-p).toString());*/response.reset();//告诉客户端允许断点续传多线程连接下载,响应的格式是:Accept-Ranges:bytesresponse.setHeader("Accept-Ranges","bytes");//如果是第一次下,还没有断点续传,状态是默认的200,无需显式设置;响应的格式是:HTTP/1.1200OKif(pastLength!=0){//不是从最开始下载,//响应的格式是://Content-Range:bytes[文件块的开始字节]-[文件的总大小-1]/[文件的总大小]log.info("----------------------------不是从开始进行下载!服务器即将开始断点续传...");switch(rangeSwitch){case1:{//针对bytes=27000-的请求StringcontentRange=newStringBuffer("bytes").append(newLong(pastLength).toString()).append("-").append(newLong(fileLength-1).toString()).append("/").append(newLong(fileLength).toString()).toString();response.setHeader("Content-Range",contentRange);break;}case2:{//针对bytes=27000-39000的请求StringcontentRange=rangeBytes+"/"+newLong(fileLength).toString();response.setHeader("Content-Range",contentRange);break;}default:{break;}}}else{//是从开始下载log.info("----------------------------是从开始进行下载!");}try{response.addHeader("Content-Disposition","attachment;filename=""+downloadFile.getName()+""");response.setContentType(CommonUtil.setContentType(downloadFile.getName()));//settheMIMEtype.response.addHeader("Content-Length",String.valueOf(contentLength));os=response.getOutputStream();out=newBufferedOutputStream(os);raf=newRandomAccessFile(downloadFile,"r");try{switch(rangeSwitch){case0:{//普通下载,或者从头开始的下载//同1}case1:{//针对bytes=27000-的请求raf.seek(pastLength);//形如bytes=969998336-的客户端请求,跳过969998336个字节intn=0;while((n=raf.read(b,0,1024))!=-1){out.write(b,0,n);}break;}case2:{//针对bytes=27000-39000的请求raf.seek(pastLength-1);//形如bytes=1275856879-1275877358的客户端请求,找到第1275856879个字节intn=0;longreadLength=0;//记录已读字节数while(readLength<=contentLength-1024){//大部分字节在这里读取n=raf.read(b,0,1024);readLength+=1024;out.write(b,0,n);}if(readLength<=contentLength){//余下的不足1024个字节在这里读取n=raf.read(b,0,(int)(contentLength-readLength));out.write(b,0,n);}////raf.seek(pastLength);//形如bytes=1275856879-1275877358的客户端请求,找到第1275856879个字节//while(raf.getFilePointer()<toLength){//out.write(raf.read());//}break;}default:{break;}}out.flush();}catch(IOExceptionie){/***在写数据的时候,*对于ClientAbortException之类的异常,*是因为客户端取消了下载,而服务器端继续向浏览器写入数据时,*抛出这个异常,这个是正常的。*尤其是对于迅雷这种吸血的客户端软件,*明明已经有一个线程在读取bytes=1275856879-1275877358,*如果短时间内没有读取完毕,迅雷会再启第二个、第三个。。。线程来读取相同的字节段,*直到有一个线程读取完毕,迅雷会KILL掉其他正在下载同一字节段的线程,*强行中止字节读出,造成服务器抛ClientAbortException。*所以,我们忽略这种异常*///ignore}}catch(Exceptione){log.error(e.getMessage(),e);}finally{if(out!=null){try{out.close();}catch(IOExceptione){log.error(e.getMessage(),e);}}if(raf!=null){try{raf.close();}catch(IOExceptione){log.error(e.getMessage(),e);}}}}}

解决方案三:
其实基本也就这样,但是在循环里os.write(buffer,0,n);后面flush一下就好了
解决方案四:
大文件报溢出?真的么?为啥catch不输出异常?为啥你要在finally里面关os,os是这个函数开的么?为啥close都在一个try里?

时间: 2024-09-10 07:48:03

RESPONSE IO流的方式下载,大文件如何处理,求教!的相关文章

代码-从服务器上下载的压缩文件,通过流的方式怎么读取文件中的内容。

问题描述 从服务器上下载的压缩文件,通过流的方式怎么读取文件中的内容. 如何用java代码实现压缩文件的读取? 例如从银行服务器上下载对账文件后,为了不在本地保存文件. 压缩文件中的文件格式是俩个文本文件,怎么用流的方式读取到压缩文件中的文件内容. 解决方案 ZipEntry http://daoshud1.iteye.com/blog/2012362 解决方案二: http://www.cnblogs.com/kgdxpr/archive/2013/05/20/3088254.html 解决方

ASP.Net下载大文件的实现方法

这篇文章主要介绍了ASP.Net下载大文件的实现方法,较为详细的分析了实现大文件下载的思路及具体注意事项,需要的朋友可以参考下 本文实例讲述了ASP.Net下载大文件的实现方法.分享给大家供大家参考.具体分析如下: 当我们的网站需要支持下载大文件时,如果不做控制可能会导致用户在访问下载页面时发生无响应,使得浏览器崩溃.可以参考如下代码来避免这个问题. 关于此代码的几点说明: 1. 将数据分成较小的部分,然后将其移动到输出流以供下载,从而获取这些数据. 2. 根据下载的文件类型来指定 Respon

ASP.Net下载大文件的实现方法_实用技巧

本文实例讲述了ASP.Net下载大文件的实现方法.分享给大家供大家参考.具体分析如下: 当我们的网站需要支持下载大文件时,如果不做控制可能会导致用户在访问下载页面时发生无响应,使得浏览器崩溃.可以参考如下代码来避免这个问题. 关于此代码的几点说明: 1. 将数据分成较小的部分,然后将其移动到输出流以供下载,从而获取这些数据. 2. 根据下载的文件类型来指定 Response.ContentType .(参考OSChina的这个网址可以找到大部分文件类型的对照表:http://tool.oschi

在ASP.NET中支持断点续传下载大文件(ZT)源码_实用技巧

IE的自带下载功能中没有断点续传功能,要实现断点续传功能,需要用到HTTP协议中鲜为人知的几个响应头和请求头. 一. 两个必要响应头Accept-Ranges.ETag 客户端每次提交下载请求时,服务端都要添加这两个响应头,以保证客户端和服务端将此下载识别为可以断点续传的下载: Accept-Ranges:告知下载客户端这是一个可以恢复续传的下载,存放本次下载的开始字节位置.文件的字节大小: ETag:保存文件的唯一标识(我在用的文件名+文件最后修改时间,以便续传请求时对文件进行验证): Las

百度云盘下载大文件不用百度云管家的方法

  [一].先将你要下载的大文件转存到你自己的百度云网盘,这一步必须; 例如:我将这个5G的文件转存到我的网盘 [二].转存后回到你自己的百度网盘主页,接下来,把你的目光移向浏览器的地址栏: 是不是看见一个英文字母"disk"?没错,把它改掉,改成"wap",哦,天哪!我们居然来到了百度云手机版!找到你转存的大文件,点击就可直接使用你的浏览器默认下载工具了: [三].直接点击[下载链接]: 立即进入你的浏览器默认下载界面(你也可以调用迅雷等工具下载了): [原理点解

百度云盘下载大文件却不用安装百度云管家怎么办

  一.先将你要下载的大文件转存到你自己的百度云网盘,这一步必须; 例如:我将这个5G的文件转存到我的网盘 二.转存后回到你自己的百度网盘主页,接下来,把你的目光移向浏览器的地址栏: 是不是看见一个英文字母"disk"?没错,把它改掉,改成"wap",哦,天哪!我们居然来到了百度云手机版!找到你转存的大文件,点击就可直接使用你的浏览器默认下载工具了: 三.直接点击[下载链接]: 立即进入你的浏览器默认下载界面(你也可以调用迅雷等工具下载了): 原理分析:就是将百度云

百度网盘如何直接下载大文件

  百度云盘大文件直接下载教程(免客户端下载大文件)最新简单方法: 1.你的浏览器一定是Chrome浏览器或者基于Chromium内核的浏览器如360浏览器极速版. 2.前往网页百度云资源页面,如图 3.如果正常点击下载,那么肯定会提示"你下载的文件过大,需要使用百度云管家". 那么重点来了! 在你的chrome浏览器地址栏里,在百度云页面网址前加上"https://"前缀,这是一个安全协议,百度云无法跳转.然后直接点击下载,就不会提示下载百度云了. 此前办法如下:

java 通过apache ftp读取大文件或者下载大文件

问题描述 java 通过apache ftp读取大文件或者下载大文件 本人技术短,参照网上各位大侠的帖子写了登录ftp去读取ftp下面文件然后直接存进数据库的代码 ,但是我的代码只能读取一些小的文件,文件大点就报内存溢出.谁可以给个能在ftp上面下载大文件或者能够直接读取ftp服务器上面的大文件然后直接解析存进数据库的代码例子.不胜感激. 解决方案 内存溢出..说明内存方步下文件..ftp取到liu后写入文件吧...ps都内存溢出了..你不可能在内存中解析的..有可能是你jvm内存设置太小所致.

jmeter-怎么用Jmeter测试多用户下载大文件?

问题描述 怎么用Jmeter测试多用户下载大文件? 怎么配置那个请求里面的参数,Monitor Results 里面怎么一直没有数据? 解决方案 用jmeter进行多用户并发压力测试 解决方案二: 测试工具会有对应的技术指导啊,我们的工具就有