1.需求:
根据Url下载大文件,本地创建文件,从输入流读取并写入文件,要求能满足大文件的下载,不能出现OOM
2.引入依赖
<!-- OK HTTP -->
<dependency><groupId>com.squareup.okhttp3</groupId><artifactId>okhttp</artifactId><version>4.12.0</version>
</dependency>
<!-- Hutool工具包 -->
<dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.7.16</version>
</dependency>
3.下载文件代码
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.net.URLDecoder;
import java.nio.charset.StandardCharsets;/*** 下载文件并保存* @param url 下载地址* @param folder 本地保存文件夹路径,比如:E:\test\down* @return 文件(下载失败返回null)*/
public File downloadFile(String url, String folder){OkHttpClient client = new OkHttpClient();Request request = new Request.Builder().url(url).build();try(Response response = client.newCall(request).execute()){if(response.isSuccessful()){if(Objects.isNull(response.body())){logger.info("下载失败,响应体为空");return null;}//从Url提取文件名String fileName = getFileNameFromUrl(url);//拼接完整文件路径String filePath = folder + File.separator + fileName;//创建本地文件File file = new File(filePath);FileUtil.touch(file);try(InputStream in = response.body().byteStream();//获取响应输入流FileOutputStream out = new FileOutputStream(file)//创建文件输出流){//写入本地文件int len;byte[] buffer = new byte[4096];while((len = in.read(buffer)) != -1) { //从输入流中读取数据到缓冲区out.write(buffer, 0, len); //将缓冲区的数据写入输出流}out.flush(); //刷新输出流缓冲区}return file;}else{logger.info("响应失败:httpStatus={}", response.code());return null;}}catch (Exception e){logger.info("文件下载失败,地址:{},错误:{}", url, e.getMessage(), e);return null;}
}/*** 从Url提取文件名* @param url 文件路径* @return 文件名*/
private static String getFileNameFromUrl(String url){String uri = URLDecoder.decode(url.trim(), StandardCharsets.UTF_8);int index = uri.lastIndexOf("/");return index==-1 ? uri : uri.substring(index+1);
}