mirror of
https://github.com/qaiu/netdisk-fast-download.git
synced 2025-12-16 12:23:03 +00:00
feat: 新增客户端协议生成系统,支持8种主流下载工具
🚀 核心功能 - 新增完整的客户端下载链接生成器系统 - 支持ARIA2、Motrix、比特彗星、迅雷、wget、cURL、IDM、FDM、PowerShell等8种客户端 - 自动处理防盗链参数(User-Agent、Referer、Cookie等) - 提供可扩展的生成器架构,支持自定义客户端 🔧 技术实现 - ClientLinkGeneratorFactory: 工厂模式管理生成器 - DownloadLinkMeta: 元数据存储下载信息 - ClientLinkUtils: 便捷工具类 - 线程安全的ConcurrentHashMap设计 🌐 前端集成 - 新增ClientLinks.vue界面,支持客户端链接展示 - Element Plus图标系统,混合图标显示 - 客户端检测逻辑优化,避免自动打开外部应用 - 移动端和PC端环境判断 📚 文档完善 - 完整的CLIENT_LINK_GENERATOR_GUIDE.md使用指南 - API文档和测试用例 - 输出示例和最佳实践 从单纯的网盘解析工具升级为完整的下载解决方案生态
This commit is contained in:
120
web-service/doc/CLIENT_LINKS_API.md
Normal file
120
web-service/doc/CLIENT_LINKS_API.md
Normal file
@@ -0,0 +1,120 @@
|
||||
# 客户端下载链接 API 文档
|
||||
|
||||
## 概述
|
||||
|
||||
新增的客户端下载链接 API 允许用户获取各种下载客户端格式的下载链接,包括 cURL、PowerShell、Aria2、迅雷等。
|
||||
|
||||
## API 端点
|
||||
|
||||
### 1. 获取所有客户端下载链接
|
||||
|
||||
**端点**: `GET /v2/clientLinks`
|
||||
|
||||
**参数**:
|
||||
- `url` (必需): 分享链接
|
||||
- `pwd` (可选): 提取码
|
||||
|
||||
**响应示例**:
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"directLink": "https://example.com/file.zip",
|
||||
"fileName": "test-file.zip",
|
||||
"fileSize": 1024000,
|
||||
"clientLinks": {
|
||||
"CURL": "curl -L -H \"User-Agent: Mozilla/5.0...\" -o \"test-file.zip\" \"https://example.com/file.zip\"",
|
||||
"POWERSHELL": "$session = New-Object Microsoft.PowerShell.Commands.WebRequestSession...",
|
||||
"ARIA2": "aria2c --header=\"User-Agent: Mozilla/5.0...\" --out=\"test-file.zip\" \"https://example.com/file.zip\"",
|
||||
"THUNDER": "thunder://QUFodHRwczovL2V4YW1wbGUuY29tL2ZpbGUuemlwWlo=",
|
||||
"IDM": "idm://https://example.com/file.zip",
|
||||
"WGET": "wget --header=\"User-Agent: Mozilla/5.0...\" -O \"test-file.zip\" \"https://example.com/file.zip\"",
|
||||
"BITCOMET": "bitcomet://https://example.com/file.zip",
|
||||
"MOTRIX": "{\"url\":\"https://example.com/file.zip\",\"out\":\"test-file.zip\"}",
|
||||
"FDM": "https://example.com/file.zip"
|
||||
},
|
||||
"supportedClients": {
|
||||
"curl": "cURL 命令",
|
||||
"wget": "wget 命令",
|
||||
"aria2": "Aria2",
|
||||
"idm": "IDM",
|
||||
"thunder": "迅雷",
|
||||
"bitcomet": "比特彗星",
|
||||
"motrix": "Motrix",
|
||||
"fdm": "Free Download Manager",
|
||||
"powershell": "PowerShell"
|
||||
},
|
||||
"parserInfo": "百度网盘 - pan"
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 获取指定类型的客户端下载链接
|
||||
|
||||
**端点**: `GET /v2/clientLink`
|
||||
|
||||
**参数**:
|
||||
- `url` (必需): 分享链接
|
||||
- `pwd` (可选): 提取码
|
||||
- `clientType` (必需): 客户端类型 (curl, wget, aria2, idm, thunder, bitcomet, motrix, fdm, powershell)
|
||||
|
||||
**响应**: 直接返回指定类型的客户端下载链接字符串
|
||||
|
||||
## 支持的客户端类型
|
||||
|
||||
| 客户端类型 | 代码 | 说明 | 输出格式 |
|
||||
|-----------|------|------|----------|
|
||||
| cURL | `curl` | 命令行工具 | curl 命令 |
|
||||
| wget | `wget` | 命令行工具 | wget 命令 |
|
||||
| Aria2 | `aria2` | 命令行/RPC | aria2c 命令 |
|
||||
| IDM | `idm` | Windows 下载管理器 | idm:// 协议链接 |
|
||||
| 迅雷 | `thunder` | 国内主流下载工具 | thunder:// 协议链接 |
|
||||
| 比特彗星 | `bitcomet` | BT 下载工具 | bitcomet:// 协议链接 |
|
||||
| Motrix | `motrix` | 跨平台下载工具 | JSON 格式 |
|
||||
| FDM | `fdm` | Free Download Manager | 文本格式 |
|
||||
| PowerShell | `powershell` | Windows PowerShell | PowerShell 命令 |
|
||||
|
||||
## 使用示例
|
||||
|
||||
### 获取所有客户端链接
|
||||
```bash
|
||||
curl "http://localhost:8080/v2/clientLinks?url=https://pan.baidu.com/s/1test123&pwd=1234"
|
||||
```
|
||||
|
||||
### 获取 cURL 命令
|
||||
```bash
|
||||
curl "http://localhost:8080/v2/clientLink?url=https://pan.baidu.com/s/1test123&pwd=1234&clientType=curl"
|
||||
```
|
||||
|
||||
### 获取 PowerShell 命令
|
||||
```bash
|
||||
curl "http://localhost:8080/v2/clientLink?url=https://pan.baidu.com/s/1test123&pwd=1234&clientType=powershell"
|
||||
```
|
||||
|
||||
## 错误处理
|
||||
|
||||
当请求失败时,API 会返回错误信息:
|
||||
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"error": "解析分享链接失败: 具体错误信息"
|
||||
}
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **Referer 支持**: CowTool (奶牛快传) 解析器已正确实现 Referer 请求头支持
|
||||
2. **请求头处理**: 所有客户端链接都会包含必要的请求头(如 User-Agent、Referer、Cookie 等)
|
||||
3. **特殊字符转义**: PowerShell 命令会自动转义特殊字符(引号、美元符号等)
|
||||
4. **异步处理**: API 使用异步处理,确保高性能
|
||||
5. **错误容错**: 即使某个客户端类型生成失败,其他类型仍会正常生成
|
||||
|
||||
## 集成说明
|
||||
|
||||
该功能已集成到现有的解析器框架中:
|
||||
|
||||
- **ParserApi**: 新增两个 API 端点
|
||||
- **ClientLinkResp**: 新的响应模型
|
||||
- **CowTool**: 已支持 Referer 请求头
|
||||
- **PowerShell**: 新增 PowerShell 格式支持
|
||||
|
||||
所有功能都经过测试验证,可以安全使用。
|
||||
@@ -6,11 +6,13 @@ import cn.qaiu.entity.ShareLinkInfo;
|
||||
import cn.qaiu.lz.common.cache.CacheManager;
|
||||
import cn.qaiu.lz.common.util.URLParamUtil;
|
||||
import cn.qaiu.lz.web.model.CacheLinkInfo;
|
||||
import cn.qaiu.lz.web.model.ClientLinkResp;
|
||||
import cn.qaiu.lz.web.model.LinkInfoResp;
|
||||
import cn.qaiu.lz.web.model.StatisticsInfo;
|
||||
import cn.qaiu.lz.web.service.DbService;
|
||||
import cn.qaiu.parser.PanDomainTemplate;
|
||||
import cn.qaiu.parser.ParserCreate;
|
||||
import cn.qaiu.parser.clientlink.ClientLinkType;
|
||||
import cn.qaiu.vx.core.annotaions.RouteHandler;
|
||||
import cn.qaiu.vx.core.annotaions.RouteMapping;
|
||||
import cn.qaiu.vx.core.enums.RouteMethod;
|
||||
@@ -244,4 +246,151 @@ public class ParserApi {
|
||||
.replace("-", "")
|
||||
.replace(":", "");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取客户端下载链接
|
||||
*
|
||||
* @param request HTTP请求
|
||||
* @param pwd 提取码
|
||||
* @return 客户端下载链接响应
|
||||
*/
|
||||
@RouteMapping(value = "/clientLinks", method = RouteMethod.GET)
|
||||
public Future<ClientLinkResp> getClientLinks(HttpServerRequest request, String pwd) {
|
||||
Promise<ClientLinkResp> promise = Promise.promise();
|
||||
|
||||
try {
|
||||
String shareUrl = URLParamUtil.parserParams(request);
|
||||
ParserCreate parserCreate = ParserCreate.fromShareUrl(shareUrl).setShareLinkInfoPwd(pwd);
|
||||
ShareLinkInfo shareLinkInfo = parserCreate.getShareLinkInfo();
|
||||
|
||||
// 使用默认方法解析并生成客户端链接
|
||||
parserCreate.createTool().parseWithClientLinks()
|
||||
.onSuccess(clientLinks -> {
|
||||
try {
|
||||
ClientLinkResp response = buildClientLinkResponse(shareLinkInfo, clientLinks);
|
||||
promise.complete(response);
|
||||
} catch (Exception e) {
|
||||
log.error("处理客户端链接结果失败", e);
|
||||
promise.fail(new RuntimeException("处理客户端链接结果失败: " + e.getMessage()));
|
||||
}
|
||||
})
|
||||
.onFailure(error -> {
|
||||
log.error("解析分享链接失败", error);
|
||||
promise.fail(new RuntimeException("解析分享链接失败: " + error.getMessage()));
|
||||
});
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("解析请求参数失败", e);
|
||||
promise.fail(new RuntimeException("解析请求参数失败: " + e.getMessage()));
|
||||
}
|
||||
|
||||
return promise.future();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定类型的客户端下载链接
|
||||
*
|
||||
* @param request HTTP请求
|
||||
* @param pwd 提取码
|
||||
* @param clientType 客户端类型 (curl, wget, aria2, idm, thunder, bitcomet, motrix, fdm, powershell)
|
||||
* @return 指定类型的客户端下载链接
|
||||
*/
|
||||
@RouteMapping(value = "/clientLink", method = RouteMethod.GET)
|
||||
public Future<String> getClientLink(HttpServerRequest request, String pwd, String clientType) {
|
||||
Promise<String> promise = Promise.promise();
|
||||
|
||||
try {
|
||||
String shareUrl = URLParamUtil.parserParams(request);
|
||||
ParserCreate parserCreate = ParserCreate.fromShareUrl(shareUrl).setShareLinkInfoPwd(pwd);
|
||||
|
||||
// 使用默认方法解析并生成客户端链接
|
||||
parserCreate.createTool().parseWithClientLinks()
|
||||
.onSuccess(clientLinks -> {
|
||||
try {
|
||||
String clientLink = extractClientLinkByType(clientLinks, clientType);
|
||||
if (clientLink != null) {
|
||||
promise.complete(clientLink);
|
||||
} else {
|
||||
promise.fail("无法生成 " + clientType + " 格式的下载链接");
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
promise.fail("不支持的客户端类型: " + clientType);
|
||||
} catch (Exception e) {
|
||||
log.error("获取客户端链接失败", e);
|
||||
promise.fail("获取客户端链接失败: " + e.getMessage());
|
||||
}
|
||||
})
|
||||
.onFailure(error -> {
|
||||
log.error("解析分享链接失败", error);
|
||||
promise.fail("解析分享链接失败: " + error.getMessage());
|
||||
});
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("解析请求参数失败", e);
|
||||
promise.fail("解析请求参数失败: " + e.getMessage());
|
||||
}
|
||||
|
||||
return promise.future();
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建客户端链接响应
|
||||
*
|
||||
* @param shareLinkInfo 分享链接信息
|
||||
* @param clientLinks 客户端链接映射
|
||||
* @return 客户端链接响应
|
||||
*/
|
||||
private ClientLinkResp buildClientLinkResponse(ShareLinkInfo shareLinkInfo, Map<ClientLinkType, String> clientLinks) {
|
||||
// 从 otherParam 中获取直链
|
||||
String directLink = (String) shareLinkInfo.getOtherParam().get("downloadUrl");
|
||||
Map<String, String> supportedClients = buildSupportedClientsMap();
|
||||
FileInfo fileInfo = extractFileInfo(shareLinkInfo);
|
||||
|
||||
return ClientLinkResp.builder()
|
||||
.success(true)
|
||||
.directLink(directLink)
|
||||
.fileName(fileInfo != null ? fileInfo.getFileName() : null)
|
||||
.fileSize(fileInfo != null ? fileInfo.getSize() : null)
|
||||
.clientLinks(clientLinks)
|
||||
.supportedClients(supportedClients)
|
||||
.parserInfo(shareLinkInfo.getPanName() + " - " + shareLinkInfo.getType())
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建支持的客户端类型映射
|
||||
*
|
||||
* @return 客户端类型映射
|
||||
*/
|
||||
private Map<String, String> buildSupportedClientsMap() {
|
||||
Map<String, String> supportedClients = new HashMap<>();
|
||||
for (ClientLinkType type : ClientLinkType.values()) {
|
||||
supportedClients.put(type.getCode(), type.getDisplayName());
|
||||
}
|
||||
return supportedClients;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从ShareLinkInfo中提取文件信息
|
||||
*
|
||||
* @param shareLinkInfo 分享链接信息
|
||||
* @return 文件信息,如果不存在则返回null
|
||||
*/
|
||||
private FileInfo extractFileInfo(ShareLinkInfo shareLinkInfo) {
|
||||
Object fileInfo = shareLinkInfo.getOtherParam().get("fileInfo");
|
||||
return fileInfo instanceof FileInfo ? (FileInfo) fileInfo : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据客户端类型提取对应的客户端链接
|
||||
*
|
||||
* @param clientLinks 客户端链接映射
|
||||
* @param clientType 客户端类型
|
||||
* @return 客户端链接,如果不存在则返回null
|
||||
* @throws IllegalArgumentException 如果客户端类型不支持
|
||||
*/
|
||||
private String extractClientLinkByType(Map<ClientLinkType, String> clientLinks, String clientType) {
|
||||
ClientLinkType type = ClientLinkType.valueOf(clientType.toUpperCase());
|
||||
return clientLinks.get(type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
package cn.qaiu.lz.web.model;
|
||||
|
||||
import cn.qaiu.parser.clientlink.ClientLinkType;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 客户端下载链接响应模型
|
||||
*
|
||||
* @author <a href="https://qaiu.top">QAIU</a>
|
||||
* Create at 2025/01/21
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class ClientLinkResp {
|
||||
|
||||
/**
|
||||
* 是否成功
|
||||
*/
|
||||
private boolean success;
|
||||
|
||||
/**
|
||||
* 错误信息
|
||||
*/
|
||||
private String error;
|
||||
|
||||
/**
|
||||
* 直链URL
|
||||
*/
|
||||
private String directLink;
|
||||
|
||||
/**
|
||||
* 文件名
|
||||
*/
|
||||
private String fileName;
|
||||
|
||||
/**
|
||||
* 文件大小
|
||||
*/
|
||||
private Long fileSize;
|
||||
|
||||
/**
|
||||
* 所有客户端下载链接
|
||||
*/
|
||||
private Map<ClientLinkType, String> clientLinks;
|
||||
|
||||
/**
|
||||
* 支持的客户端类型列表
|
||||
*/
|
||||
private Map<String, String> supportedClients;
|
||||
|
||||
/**
|
||||
* 解析信息
|
||||
*/
|
||||
private String parserInfo;
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
### 客户端下载链接 API 测试
|
||||
|
||||
### 环境变量
|
||||
@host = http://localhost:6400
|
||||
@testUrl = https://www.kdocs.cn/l/ck0azivLlDi3
|
||||
@testPwd =
|
||||
@cowUrl = https://cowtransfer.com/s/test123
|
||||
|
||||
@lanzouUrl = https://wwsd.lanzoue.com/iLany1e9bbbi
|
||||
|
||||
### 1. 获取所有客户端下载链接
|
||||
GET {{host}}/v2/clientLinks?url={{lanzouUrl}}&pwd={{testPwd}}
|
||||
|
||||
### 2. 获取指定类型的客户端下载链接 - cURL
|
||||
GET {{host}}/v2/clientLink?url={{testUrl}}&pwd={{testPwd}}&clientType=curl
|
||||
|
||||
### 3. 获取指定类型的客户端下载链接 - PowerShell
|
||||
GET {{host}}/v2/clientLink?url={{testUrl}}&pwd={{testPwd}}&clientType=powershell
|
||||
|
||||
### 4. 获取指定类型的客户端下载链接 - Aria2
|
||||
GET {{host}}/v2/clientLink?url={{testUrl}}&pwd={{testPwd}}&clientType=aria2
|
||||
|
||||
### 5. 获取指定类型的客户端下载链接 - 迅雷
|
||||
GET {{host}}/v2/clientLink?url={{testUrl}}&pwd={{testPwd}}&clientType=thunder
|
||||
|
||||
### 6. 获取指定类型的客户端下载链接 - IDM
|
||||
GET {{host}}/v2/clientLink?url={{testUrl}}&pwd={{testPwd}}&clientType=idm
|
||||
|
||||
### 7. 获取指定类型的客户端下载链接 - wget
|
||||
GET {{host}}/v2/clientLink?url={{testUrl}}&pwd={{testPwd}}&clientType=wget
|
||||
|
||||
### 8. 获取指定类型的客户端下载链接 - 比特彗星
|
||||
GET {{host}}/v2/clientLink?url={{testUrl}}&pwd={{testPwd}}&clientType=bitcomet
|
||||
|
||||
### 9. 获取指定类型的客户端下载链接 - Motrix
|
||||
GET {{host}}/v2/clientLink?url={{testUrl}}&pwd={{testPwd}}&clientType=motrix
|
||||
|
||||
### 10. 获取指定类型的客户端下载链接 - FDM
|
||||
GET {{host}}/v2/clientLink?url={{testUrl}}&pwd={{testPwd}}&clientType=fdm
|
||||
|
||||
### 11. 测试不支持的客户端类型
|
||||
GET {{host}}/v2/clientLink?url={{testUrl}}&pwd={{testPwd}}&clientType=invalid
|
||||
|
||||
### 12. 测试奶牛快传(需要 Referer)
|
||||
GET {{host}}/v2/clientLinks?url={{cowUrl}}&pwd=
|
||||
|
||||
### 13. 测试空参数
|
||||
GET {{host}}/v2/clientLinks
|
||||
|
||||
### 14. 测试无效URL
|
||||
GET {{host}}/v2/clientLinks?url=invalid-url&pwd=1234
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
Reference in New Issue
Block a user