mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
add downloadFileFromUrl
This commit is contained in:
parent
9a94f2e750
commit
9eec8ec6e0
@ -8,6 +8,7 @@
|
|||||||
### 新特性
|
### 新特性
|
||||||
* 【core 】 StrUtil增加firstNonXXX方法(issue#1020@Github)
|
* 【core 】 StrUtil增加firstNonXXX方法(issue#1020@Github)
|
||||||
* 【core 】 BeanCopier修改规则,可选bean拷贝空字段报错问题(pr#160@Gitee)
|
* 【core 】 BeanCopier修改规则,可选bean拷贝空字段报错问题(pr#160@Gitee)
|
||||||
|
* 【http 】 HttpUtil增加downloadFileFromUrl(pr#1023@Github)
|
||||||
|
|
||||||
### Bug修复#
|
### Bug修复#
|
||||||
* 【poi 】 修复ExcelBase.isXlsx方法判断问题(issue#I1S502@Gitee)
|
* 【poi 】 修复ExcelBase.isXlsx方法判断问题(issue#I1S502@Gitee)
|
||||||
|
@ -1,14 +1,26 @@
|
|||||||
package cn.hutool.http;
|
package cn.hutool.http;
|
||||||
|
|
||||||
import cn.hutool.core.convert.Convert;
|
import cn.hutool.core.convert.Convert;
|
||||||
import cn.hutool.core.io.*;
|
import cn.hutool.core.io.FastByteArrayOutputStream;
|
||||||
|
import cn.hutool.core.io.FileUtil;
|
||||||
|
import cn.hutool.core.io.IORuntimeException;
|
||||||
|
import cn.hutool.core.io.IoUtil;
|
||||||
|
import cn.hutool.core.io.StreamProgress;
|
||||||
|
import cn.hutool.core.lang.Assert;
|
||||||
import cn.hutool.core.util.CharsetUtil;
|
import cn.hutool.core.util.CharsetUtil;
|
||||||
import cn.hutool.core.util.ReUtil;
|
import cn.hutool.core.util.ReUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.hutool.core.util.URLUtil;
|
import cn.hutool.core.util.URLUtil;
|
||||||
import cn.hutool.http.cookie.GlobalCookieManager;
|
import cn.hutool.http.cookie.GlobalCookieManager;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.Closeable;
|
||||||
|
import java.io.EOFException;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
import java.net.HttpCookie;
|
import java.net.HttpCookie;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -19,21 +31,32 @@ import java.util.Map.Entry;
|
|||||||
* 非线程安全对象
|
* 非线程安全对象
|
||||||
*
|
*
|
||||||
* @author Looly
|
* @author Looly
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class HttpResponse extends HttpBase<HttpResponse> implements Closeable {
|
public class HttpResponse extends HttpBase<HttpResponse> implements Closeable {
|
||||||
|
|
||||||
/** 持有连接对象 */
|
/**
|
||||||
|
* 持有连接对象
|
||||||
|
*/
|
||||||
protected HttpConnection httpConnection;
|
protected HttpConnection httpConnection;
|
||||||
/** Http请求原始流 */
|
/**
|
||||||
|
* Http请求原始流
|
||||||
|
*/
|
||||||
protected InputStream in;
|
protected InputStream in;
|
||||||
/** 是否异步,异步下只持有流,否则将在初始化时直接读取body内容 */
|
/**
|
||||||
|
* 是否异步,异步下只持有流,否则将在初始化时直接读取body内容
|
||||||
|
*/
|
||||||
private volatile boolean isAsync;
|
private volatile boolean isAsync;
|
||||||
/** 响应状态码 */
|
/**
|
||||||
|
* 响应状态码
|
||||||
|
*/
|
||||||
protected int status;
|
protected int status;
|
||||||
/** 是否忽略读取Http响应体 */
|
/**
|
||||||
|
* 是否忽略读取Http响应体
|
||||||
|
*/
|
||||||
private final boolean ignoreBody;
|
private final boolean ignoreBody;
|
||||||
/** 从响应中获取的编码 */
|
/**
|
||||||
|
* 从响应中获取的编码
|
||||||
|
*/
|
||||||
private Charset charsetFromResponse;
|
private Charset charsetFromResponse;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -84,6 +107,7 @@ public class HttpResponse extends HttpBase<HttpResponse> implements Closeable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------- Http Response Header start
|
// ---------------------------------------------------------------- Http Response Header start
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取内容编码
|
* 获取内容编码
|
||||||
*
|
*
|
||||||
@ -178,6 +202,7 @@ public class HttpResponse extends HttpBase<HttpResponse> implements Closeable {
|
|||||||
// ---------------------------------------------------------------- Http Response Header end
|
// ---------------------------------------------------------------- Http Response Header end
|
||||||
|
|
||||||
// ---------------------------------------------------------------- Body start
|
// ---------------------------------------------------------------- Body start
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得服务区响应流<br>
|
* 获得服务区响应流<br>
|
||||||
* 异步模式下获取Http原生流,同步模式下获取获取到的在内存中的副本<br>
|
* 异步模式下获取Http原生流,同步模式下获取获取到的在内存中的副本<br>
|
||||||
@ -246,18 +271,14 @@ public class HttpResponse extends HttpBase<HttpResponse> implements Closeable {
|
|||||||
*
|
*
|
||||||
* @param destFile 写出到的文件
|
* @param destFile 写出到的文件
|
||||||
* @param streamProgress 进度显示接口,通过实现此接口显示下载进度
|
* @param streamProgress 进度显示接口,通过实现此接口显示下载进度
|
||||||
*
|
|
||||||
* @return 写出bytes数
|
* @return 写出bytes数
|
||||||
*
|
|
||||||
* @since 3.3.2
|
* @since 3.3.2
|
||||||
*/
|
*/
|
||||||
public long writeBody(File destFile, StreamProgress streamProgress) {
|
public long writeBody(File destFile, StreamProgress streamProgress) {
|
||||||
if (null == destFile) {
|
Assert.notNull(destFile, "[destFile] is null!");
|
||||||
throw new NullPointerException("[destFile] is null!");
|
|
||||||
}
|
|
||||||
|
|
||||||
File outFile = completeFileNameFromHeader(destFile);
|
final File outFile = completeFileNameFromHeader(destFile);
|
||||||
OutputStream outputStream = FileUtil.getOutputStream(outFile);
|
final OutputStream outputStream = FileUtil.getOutputStream(outFile);
|
||||||
return writeBody(outputStream, true, streamProgress);
|
return writeBody(outputStream, true, streamProgress);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -268,9 +289,7 @@ public class HttpResponse extends HttpBase<HttpResponse> implements Closeable {
|
|||||||
* 写出后会关闭Http流(异步模式)
|
* 写出后会关闭Http流(异步模式)
|
||||||
*
|
*
|
||||||
* @param destFile 写出到的文件
|
* @param destFile 写出到的文件
|
||||||
*
|
|
||||||
* @return 写出bytes数
|
* @return 写出bytes数
|
||||||
*
|
|
||||||
* @since 3.3.2
|
* @since 3.3.2
|
||||||
*/
|
*/
|
||||||
public long writeBody(File destFile) {
|
public long writeBody(File destFile) {
|
||||||
@ -317,11 +336,11 @@ public class HttpResponse extends HttpBase<HttpResponse> implements Closeable {
|
|||||||
* 从响应头补全下载文件名
|
* 从响应头补全下载文件名
|
||||||
*
|
*
|
||||||
* @param destFile 目标文件夹或者目标文件
|
* @param destFile 目标文件夹或者目标文件
|
||||||
*
|
|
||||||
* @return File 保存的文件
|
* @return File 保存的文件
|
||||||
|
* @since 5.4.1
|
||||||
*/
|
*/
|
||||||
public File completeFileNameFromHeader(File destFile) {
|
public File completeFileNameFromHeader(File destFile) {
|
||||||
if (!destFile.isDirectory()) {
|
if (false == destFile.isDirectory()) {
|
||||||
// 非目录直接返回
|
// 非目录直接返回
|
||||||
return destFile;
|
return destFile;
|
||||||
}
|
}
|
||||||
|
@ -5,10 +5,15 @@ import cn.hutool.core.io.FastByteArrayOutputStream;
|
|||||||
import cn.hutool.core.io.FileUtil;
|
import cn.hutool.core.io.FileUtil;
|
||||||
import cn.hutool.core.io.IoUtil;
|
import cn.hutool.core.io.IoUtil;
|
||||||
import cn.hutool.core.io.StreamProgress;
|
import cn.hutool.core.io.StreamProgress;
|
||||||
|
import cn.hutool.core.lang.Assert;
|
||||||
import cn.hutool.core.map.MapUtil;
|
import cn.hutool.core.map.MapUtil;
|
||||||
import cn.hutool.core.net.url.UrlQuery;
|
import cn.hutool.core.net.url.UrlQuery;
|
||||||
import cn.hutool.core.text.StrBuilder;
|
import cn.hutool.core.text.StrBuilder;
|
||||||
import cn.hutool.core.util.*;
|
import cn.hutool.core.util.CharsetUtil;
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import cn.hutool.core.util.ReUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import cn.hutool.core.util.URLUtil;
|
||||||
import cn.hutool.http.server.SimpleServer;
|
import cn.hutool.http.server.SimpleServer;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -310,8 +315,7 @@ public class HttpUtil {
|
|||||||
* @since 4.0.4
|
* @since 4.0.4
|
||||||
*/
|
*/
|
||||||
public static long downloadFile(String url, File destFile, int timeout, StreamProgress streamProgress) {
|
public static long downloadFile(String url, File destFile, int timeout, StreamProgress streamProgress) {
|
||||||
HttpResponse response = requestDownloadFile(url, destFile, timeout);
|
return requestDownloadFile(url, destFile, timeout).writeBody(destFile, streamProgress);
|
||||||
return response.writeBody(destFile, streamProgress);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -320,7 +324,8 @@ public class HttpUtil {
|
|||||||
* @param url 请求的url
|
* @param url 请求的url
|
||||||
* @param dest 目标文件或目录,当为目录时,取URL中的文件名,取不到使用编码后的URL做为文件名
|
* @param dest 目标文件或目录,当为目录时,取URL中的文件名,取不到使用编码后的URL做为文件名
|
||||||
*
|
*
|
||||||
* @return 文件
|
* @return 下载的文件对象
|
||||||
|
* @since 5.4.1
|
||||||
*/
|
*/
|
||||||
public static File downloadFileFromUrl(String url, String dest) {
|
public static File downloadFileFromUrl(String url, String dest) {
|
||||||
return downloadFileFromUrl(url, FileUtil.file(dest));
|
return downloadFileFromUrl(url, FileUtil.file(dest));
|
||||||
@ -332,7 +337,8 @@ public class HttpUtil {
|
|||||||
* @param url 请求的url
|
* @param url 请求的url
|
||||||
* @param destFile 目标文件或目录,当为目录时,取URL中的文件名,取不到使用编码后的URL做为文件名
|
* @param destFile 目标文件或目录,当为目录时,取URL中的文件名,取不到使用编码后的URL做为文件名
|
||||||
*
|
*
|
||||||
* @return 文件
|
* @return 下载的文件对象
|
||||||
|
* @since 5.4.1
|
||||||
*/
|
*/
|
||||||
public static File downloadFileFromUrl(String url, File destFile) {
|
public static File downloadFileFromUrl(String url, File destFile) {
|
||||||
return downloadFileFromUrl(url, destFile, null);
|
return downloadFileFromUrl(url, destFile, null);
|
||||||
@ -345,7 +351,8 @@ public class HttpUtil {
|
|||||||
* @param destFile 目标文件或目录,当为目录时,取URL中的文件名,取不到使用编码后的URL做为文件名
|
* @param destFile 目标文件或目录,当为目录时,取URL中的文件名,取不到使用编码后的URL做为文件名
|
||||||
* @param timeout 超时,单位毫秒,-1表示默认超时
|
* @param timeout 超时,单位毫秒,-1表示默认超时
|
||||||
*
|
*
|
||||||
* @return 文件
|
* @return 下载的文件对象
|
||||||
|
* @since 5.4.1
|
||||||
*/
|
*/
|
||||||
public static File downloadFileFromUrl(String url, File destFile, int timeout) {
|
public static File downloadFileFromUrl(String url, File destFile, int timeout) {
|
||||||
return downloadFileFromUrl(url, destFile, timeout, null);
|
return downloadFileFromUrl(url, destFile, timeout, null);
|
||||||
@ -358,7 +365,8 @@ public class HttpUtil {
|
|||||||
* @param destFile 目标文件或目录,当为目录时,取URL中的文件名,取不到使用编码后的URL做为文件名
|
* @param destFile 目标文件或目录,当为目录时,取URL中的文件名,取不到使用编码后的URL做为文件名
|
||||||
* @param streamProgress 进度条
|
* @param streamProgress 进度条
|
||||||
*
|
*
|
||||||
* @return 文件
|
* @return 下载的文件对象
|
||||||
|
* @since 5.4.1
|
||||||
*/
|
*/
|
||||||
public static File downloadFileFromUrl(String url, File destFile, StreamProgress streamProgress) {
|
public static File downloadFileFromUrl(String url, File destFile, StreamProgress streamProgress) {
|
||||||
return downloadFileFromUrl(url, destFile, -1, streamProgress);
|
return downloadFileFromUrl(url, destFile, -1, streamProgress);
|
||||||
@ -372,12 +380,13 @@ public class HttpUtil {
|
|||||||
* @param timeout 超时,单位毫秒,-1表示默认超时
|
* @param timeout 超时,单位毫秒,-1表示默认超时
|
||||||
* @param streamProgress 进度条
|
* @param streamProgress 进度条
|
||||||
*
|
*
|
||||||
* @return 文件
|
* @return 下载的文件对象
|
||||||
|
* @since 5.4.1
|
||||||
*/
|
*/
|
||||||
public static File downloadFileFromUrl(String url, File destFile, int timeout, StreamProgress streamProgress) {
|
public static File downloadFileFromUrl(String url, File destFile, int timeout, StreamProgress streamProgress) {
|
||||||
HttpResponse response = requestDownloadFile(url, destFile, timeout);
|
HttpResponse response = requestDownloadFile(url, destFile, timeout);
|
||||||
|
|
||||||
File outFile = response.completeFileNameFromHeader(destFile);
|
final File outFile = response.completeFileNameFromHeader(destFile);
|
||||||
long writeBytes = response.writeBody(outFile, streamProgress);
|
long writeBytes = response.writeBody(outFile, streamProgress);
|
||||||
return outFile;
|
return outFile;
|
||||||
}
|
}
|
||||||
@ -390,21 +399,20 @@ public class HttpUtil {
|
|||||||
* @param timeout 超时时间
|
* @param timeout 超时时间
|
||||||
*
|
*
|
||||||
* @return HttpResponse
|
* @return HttpResponse
|
||||||
|
* @since 5.4.1
|
||||||
*/
|
*/
|
||||||
private static HttpResponse requestDownloadFile(String url, File destFile, int timeout) {
|
private static HttpResponse requestDownloadFile(String url, File destFile, int timeout) {
|
||||||
if (StrUtil.isBlank(url)) {
|
Assert.notBlank(url, "[url] is blank !");
|
||||||
throw new NullPointerException("[url] is null!");
|
Assert.notNull(url, "[destFile] is null !");
|
||||||
}
|
|
||||||
if (null == destFile) {
|
|
||||||
throw new NullPointerException("[destFile] is null!");
|
|
||||||
}
|
|
||||||
final HttpResponse response = HttpRequest.get(url).timeout(timeout).executeAsync();
|
final HttpResponse response = HttpRequest.get(url).timeout(timeout).executeAsync();
|
||||||
if (!response.isOk()) {
|
if (response.isOk()) {
|
||||||
throw new HttpException("Server response error with status code: [{}]", response.getStatus());
|
|
||||||
}
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
throw new HttpException("Server response error with status code: [{}]", response.getStatus());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 下载远程文件
|
* 下载远程文件
|
||||||
*
|
*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user