121 lines
4.4 KiB
Java
121 lines
4.4 KiB
Java
|
|
package com.tongran.agentserver.server.file;
|
||
|
|
|
||
|
|
import java.io.BufferedInputStream;
|
||
|
|
import java.io.FileOutputStream;
|
||
|
|
import java.io.IOException;
|
||
|
|
import java.net.HttpURLConnection;
|
||
|
|
import java.net.URL;
|
||
|
|
import java.nio.file.Files;
|
||
|
|
import java.nio.file.Path;
|
||
|
|
import java.nio.file.Paths;
|
||
|
|
import java.util.concurrent.CompletableFuture;
|
||
|
|
import java.util.concurrent.ExecutorService;
|
||
|
|
import java.util.concurrent.Executors;
|
||
|
|
import java.util.function.Consumer;
|
||
|
|
|
||
|
|
public class AdvancedAsyncDownloader {
|
||
|
|
private static final ExecutorService downloadExecutor =
|
||
|
|
Executors.newFixedThreadPool(5);
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 带进度回调的异步下载
|
||
|
|
*/
|
||
|
|
public static CompletableFuture<String> downloadWithProgress(
|
||
|
|
String fileUrl,
|
||
|
|
String saveDir,
|
||
|
|
String fileName,
|
||
|
|
Consumer<Double> progressCallback) {
|
||
|
|
|
||
|
|
return CompletableFuture.supplyAsync(() -> {
|
||
|
|
try {
|
||
|
|
URL url = new URL(fileUrl);
|
||
|
|
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||
|
|
|
||
|
|
// 获取文件大小
|
||
|
|
long fileSize = connection.getContentLengthLong();
|
||
|
|
|
||
|
|
// 创建保存目录
|
||
|
|
java.nio.file.Path directory = java.nio.file.Paths.get(saveDir);
|
||
|
|
if (!java.nio.file.Files.exists(directory)) {
|
||
|
|
java.nio.file.Files.createDirectories(directory);
|
||
|
|
}
|
||
|
|
|
||
|
|
String filePath = directory.resolve(fileName != null ? fileName :
|
||
|
|
extractFileNameFromUrl(fileUrl)).toString();
|
||
|
|
|
||
|
|
try (BufferedInputStream in = new BufferedInputStream(connection.getInputStream());
|
||
|
|
FileOutputStream out = new FileOutputStream(filePath)) {
|
||
|
|
|
||
|
|
byte[] buffer = new byte[8192];
|
||
|
|
int bytesRead;
|
||
|
|
long totalRead = 0;
|
||
|
|
|
||
|
|
while ((bytesRead = in.read(buffer)) != -1) {
|
||
|
|
out.write(buffer, 0, bytesRead);
|
||
|
|
totalRead += bytesRead;
|
||
|
|
|
||
|
|
// 回调进度
|
||
|
|
if (progressCallback != null && fileSize > 0) {
|
||
|
|
double progress = (double) totalRead / fileSize * 100;
|
||
|
|
progressCallback.accept(progress);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return filePath;
|
||
|
|
} catch (Exception e) {
|
||
|
|
throw new RuntimeException("下载失败", e);
|
||
|
|
}
|
||
|
|
}, downloadExecutor);
|
||
|
|
}
|
||
|
|
|
||
|
|
private static String extractFileNameFromUrl(String fileUrl) {
|
||
|
|
// 实现文件名提取逻辑
|
||
|
|
return fileUrl.substring(fileUrl.lastIndexOf('/') + 1);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 检查目录是否存在,不存在则创建(不创建父目录)
|
||
|
|
* @param directoryPath 目录路径
|
||
|
|
* @return 创建成功返回true,否则返回false
|
||
|
|
*/
|
||
|
|
public static boolean createSingleDirectoryIfNotExists(String directoryPath) {
|
||
|
|
try {
|
||
|
|
Path path = Paths.get(directoryPath);
|
||
|
|
|
||
|
|
if (!Files.exists(path)) {
|
||
|
|
// 只创建单级目录(父目录必须存在)
|
||
|
|
Files.createDirectory(path);
|
||
|
|
System.out.println("目录创建成功: " + directoryPath);
|
||
|
|
return true;
|
||
|
|
} else {
|
||
|
|
System.out.println("目录已存在: " + directoryPath);
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
} catch (IOException e) {
|
||
|
|
System.err.println("创建目录失败: " + directoryPath);
|
||
|
|
System.err.println("错误信息: " + e.getMessage());
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 使用示例
|
||
|
|
*/
|
||
|
|
public static void main(String[] args) {
|
||
|
|
String fileUrl = "https://www.tzdsp.net/ksc-andromedae";
|
||
|
|
String saveDir = "D:/down";
|
||
|
|
|
||
|
|
downloadWithProgress(fileUrl, saveDir, null, progress -> {
|
||
|
|
System.out.printf("下载进度: %.1f%%\n", progress);
|
||
|
|
}).thenAccept(filePath -> {
|
||
|
|
System.out.println("下载完成: " + filePath);
|
||
|
|
}).exceptionally(ex -> {
|
||
|
|
System.err.println("下载错误: " + ex.getMessage());
|
||
|
|
return null;
|
||
|
|
});
|
||
|
|
|
||
|
|
// 主线程继续执行
|
||
|
|
System.out.println("异步下载已启动...");
|
||
|
|
}
|
||
|
|
}
|