/**
* Downloads from a (http/https) URL and saves to a file.
* Does not consider a connection error an Exception. Instead it returns:
*
* 0=ok
* 1=connection interrupted, timeout (but something was read)
* 2=not found (FileNotFoundException) (404)
* 3=server error (500...)
* 4=could not connect: connection timeout (no internet?) java.net.SocketTimeoutException
* 5=could not connect: (server down?) java.net.ConnectException
* 6=could not resolve host (bad host, or no internet - no dns)
*
* @param file File to write. Parent directory will be created if necessary
* @param url http/https url to connect
* @param secsConnectTimeout Seconds to wait for connection establishment
* @param secsReadTimeout Read timeout in seconds - trasmission will abort if it freezes more than this
* @return See above
* @throws IOException Only if URL is malformed or if could not create the file
*/
public static int saveUrl(final Path file, final URL url,
int secsConnectTimeout, int secsReadTimeout) throws IOException {
Files.createDirectories(file.getParent()); // make sure parent dir exists , this can throw exception
URLConnection conn = url.openConnection(); // can throw exception if bad url
if( secsConnectTimeout > 0 ) conn.setConnectTimeout(secsConnectTimeout * 1000);
if( secsReadTimeout > 0 ) conn.setReadTimeout(secsReadTimeout * 1000);
int ret = 0;
boolean somethingRead = false;
try (InputStream is = conn.getInputStream()) {
try (BufferedInputStream in = new BufferedInputStream(is); OutputStream fout = Files
.newOutputStream(file)) {
final byte data[] = new byte[8192];
int count;
while((count = in.read(data)) > 0) {
somethingRead = true;
fout.write(data, 0, count);
}
}
} catch(java.io.IOException e) {
int httpcode = 999;
try {
httpcode = ((HttpURLConnection) conn).getResponseCode();
} catch(Exception ee) {}
if( somethingRead && e instanceof java.net.SocketTimeoutException ) ret = 1;
else if( e instanceof FileNotFoundException && httpcode >= 400 && httpcode < 500 ) ret = 2;
else if( httpcode >= 400 && httpcode < 600 ) ret = 3;
else if( e instanceof java.net.SocketTimeoutException ) ret = 4;
else if( e instanceof java.net.ConnectException ) ret = 5;
else if( e instanceof java.net.UnknownHostException ) ret = 6;
else throw e;
}
return ret;
}
20 回答
这是另一个基于Brian Risk's answer的java7变体,使用了try-with语句:
试试Java NIO:
使用
transferFrom()
是 potentially 比从源通道读取并写入此通道的简单循环更有效 . 许多操作系统可以直接从源通道将字节传输到文件系统缓存中,而无需实际复制它们 .查看更多相关信息here .
Note :transferFrom中的第三个参数是要传输的最大字节数 .
Integer.MAX_VALUE
最多将传输2 ^ 31个字节,Long.MAX_VALUE
最多允许2 ^ 63个字节(大于现有的任何文件) .使用apache commons-io,只需一行代码:
更简单的nio用法:
您需要处理异常,可能是此方法的外部异常 .
下载文件需要您阅读它,无论哪种方式,您都必须以某种方式浏览文件 . 您可以直接从流中读取字节,而不是逐行读取:
这个答案几乎就像选择的答案,但有两个增强功能:它是一个方法,它关闭了FileOutputStream对象:
使用
Java 7+
时,请使用以下方法从Internet下载文件并将其保存到某个目录:文档here .
这是一个老问题,但这是一个优雅的JDK解决方案:
简洁,可读,适当封闭的资源,除了核心JDK和语言功能之外什么都不用 .
就个人而言,我发现Apache's HttpClient能够满足我对此需要做的所有事情 . Here是一个使用HttpClient的好教程
这里有许多优雅而有效的答案 . 但简洁可能会让我们失去一些有用的信息 . 特别是,一个人可能想要区别对待某种与网络相关的错误 - 例如,决定是否应该重试下载 .
这是一个不会为网络错误抛出异常的方法(仅针对真正异常的问题,因为格式错误的URL或写入文件的问题)
简单使用有一个问题:
如果您需要下载并保存非常大的文件,或者通常如果您需要自动重试,以防连接断开 .
在这种情况下我建议的是Apache HttpClient以及org.apache.commons.io.FileUtils . 例如:
它's possible to download the file with with Apache' s
HttpComponents
而不是Commons-IO
. 此代码允许您根据URL下载Java文件并将其保存在特定目标位置 .与单行代码形成对比:
此代码将为您提供对进程的更多控制,并且不仅可以指定超时,还可以指定
User-Agent
和Referer
值,这对许多网站都很重要 .总结(并以某种方式抛光和更新)以前的答案 . 以下三种方法实际上是等同的 . (我添加了显式超时,因为我认为它们是必须的,当连接丢失时,没有人希望下载永远冻结 . )
我没有发现显着的差异,对我来说都是正确的 . 它们安全有效 . (速度上的差异似乎不太相关 - 我在本地服务器上写入180Mb到SSD磁盘的时间波动在1.2到1.5左右) . 它们不需要外部库 . 所有工作都具有任意大小和(根据我的经验)HTTP重定向 .
此外,如果找不到资源,则全部抛出
FileNotFoundException
(通常是错误404),如果DNS解析失败,则抛出java.net.UnknownHostException
;其他IOException对应于传输过程中的错误 .(标记为社区维基,随时添加信息或更正)
underscore-java库中有方法U.fetch(url) .
pom.xml中:
代码示例:
您可以使用netloader for Java在1行中执行此操作:
如果您在代理后面,可以在java程序中设置代理,如下所示:
如果您不在代理服务器后面,请不要在代码中包含上面的行 . 当您在代理后面时下载文件的完整工作代码 .
以下是使用java代码从Internet下载电影的示例代码: