java实现文件断点续传下载功能
程序员文章站
2024-03-12 11:56:20
本文实例为大家分享了java断点续传下载的代码,供大家参考,具体内容如下
1. java代码
//实现文件...
本文实例为大家分享了java断点续传下载的代码,供大家参考,具体内容如下
1. java代码
//实现文件下载功能 public string downloadfile(){ file dir = new file(filepath);//获取文件路劲 if(!dir.exists()) { system.out.println("文件路径错误"); log.debug("文件路径错误"); return "failed";// 判断文件或文件夹是否存在 } file downloadfile = new file(dir, filename);//在指定目录下查找文件 if(!downloadfile.isfile()){ system.out.println("文件不存在"); log.debug("文件不存在"); return "failed";// 判断文件或文件夹是否存在 } try { downloadfileranges(downloadfile); } catch(clientabortexception e){ system.out.println("连接被终止"); log.debug("连接被终止"); } catch (ioexception e) { e.printstacktrace(); } return null; } private void downloadfileranges(file downloadfile) throws ioexception { // 要下载的文件大小 long filelength = downloadfile.length(); // 已下载的文件大小 long pastlength = 0; // 是否快车下载,否则为迅雷或其他 boolean isflashget = true; // 用于记录需要下载的结束字节数(迅雷或其他下载) long lenend = 0; // 用于记录客户端要求下载的数据范围字串 string rangebytes = request.getheader("range"); //用于随机读取写入文件 randomaccessfile raf = null; outputstream os = null; outputstream output = null; byte b[] = new byte[1024]; // 如果客户端下载请求中包含了范围 if (null != rangebytes) { // 返回码 206 response.setstatus(httpservletresponse.sc_partial_content); rangebytes = request.getheader("range").replaceall("bytes=", ""); // 判断 range 字串模式 if (rangebytes.indexof('-') == rangebytes.length() - 1) { // 无结束字节数,为快车 isflashget = true; rangebytes = rangebytes.substring(0, rangebytes.indexof('-')); pastlength = long.parselong(rangebytes.trim()); } else { // 迅雷下载 isflashget = false; string startbytes = rangebytes.substring(0, rangebytes.indexof('-')); string endbytes = rangebytes.substring( rangebytes.indexof('-') + 1, rangebytes.length()); // 已下载文件段 pastlength = long.parselong(startbytes.trim()); // 还需下载的文件字节数(从已下载文件段开始) lenend = long.parselong(endbytes); } } // 通知客户端允许断点续传,响应格式为:accept-ranges: bytes response.setheader("accept-ranges", "bytes"); // response.reset(); // 如果为第一次下载,则状态默认为 200,响应格式为: http/1.1 200 ok if (0 != pastlength) { // 内容范围字串 string contentrange = ""; // 响应格式 // content-range: bytes [文件块的开始字节]-[文件的总大小 - 1]||[文件的总大小] if (isflashget) { contentrange = new stringbuffer("bytes") .append(new long(pastlength).tostring()).append("-") .append(new long(filelength - 1).tostring()) .append("/").append(new long(filelength).tostring()) .tostring(); } else { contentrange = new stringbuffer(rangebytes).append("/") .append(new long(filelength).tostring()).tostring(); } response.setheader("content-range", contentrange); } string filename = getdownloadchinesefilename(filename); response.setheader("content-disposition", "attachment;filename=" + filename + ""); // 响应的格式是: response.setcontenttype("application/octet-stream"); response.addheader("content-length", string.valueof(filelength)); try { os = response.getoutputstream(); output = new bufferedoutputstream(os); raf = new randomaccessfile(downloadfile, "r"); // 跳过已下载字节 raf.seek(pastlength); if (isflashget) { // 快车等 int n = 0; while ((n = raf.read(b, 0, 1024)) != -1) { output.write(b, 0, n); } } else { // 迅雷等 while (raf.getfilepointer() < lenend) { output.write(raf.read()); } } output.flush(); } catch (ioexception e) { /** * 在写数据的时候 对于 clientabortexception 之类的异常 * 是因为客户端取消了下载,而服务器端继续向浏览器写入数据时, 抛出这个异常,这个是正常的。 尤其是对于迅雷这种吸血的客户端软件。 * 明明已经有一个线程在读取 bytes=1275856879-1275877358, * 如果短时间内没有读取完毕,迅雷会再启第二个、第三个。。。线程来读取相同的字节段, 直到有一个线程读取完毕,迅雷会 kill * 掉其他正在下载同一字节段的线程, 强行中止字节读出,造成服务器抛 clientabortexception。 * 所以,我们忽略这种异常 */ } finally { if(output != null) { output.close(); } if(raf != null) { raf.close(); } } } private string getdownloadchinesefilename(string paramname) { string downloadchinesefilename = ""; try { downloadchinesefilename = new string(paramname.getbytes("gbk"), "iso8859-1"); } catch (unsupportedencodingexception e) { e.printstacktrace(); } return downloadchinesefilename; } public string getfilepath() { return filepath; } public void setfilepath(string filepath) { this.filepath = filepath; } public string getfilename() { return filename; } public void setfilename(string filename) { this.filename = filename; } public httpservletrequest getrequest() { return request; } public httpservletresponse getresponse() { return response; }
2. struts部分
复制代码 代码如下:
<action name="downloadfile" class="downloadfileaction" method="downloadfile">
<result name="failed" type="redirectaction">showdownloadfilenamelist</result>
</action>
<result name="failed" type="redirectaction">showdownloadfilenamelist</result>
</action>
3. jsp部分
复制代码 代码如下:
<td><a href="downloadfile?filename=${filemap.key }&&filepath=${filemap.value }">文件下载</a></td>
上一篇: Eclipse常用快捷键总结(必看篇)
下一篇: PHP简单装饰器模式实现与用法示例