mirror of
https://github.com/qaiu/netdisk-fast-download.git
synced 2026-08-27 20:12:02 +00:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f3d95fa7c0 | |||
| 50e75168e5 | |||
| 4bc880a41b |
@@ -455,8 +455,8 @@ docker run --rm -v /var/run/docker.sock:/var/run/docker.sock containrrr/watchtow
|
|||||||
> 注意: netdisk-fast-download.service中的ExecStart的路径改为实际路径
|
> 注意: netdisk-fast-download.service中的ExecStart的路径改为实际路径
|
||||||
```shell
|
```shell
|
||||||
cd ~
|
cd ~
|
||||||
wget -O netdisk-fast-download.zip https://github.com/qaiu/netdisk-fast-download/releases/download/v0.4.2/netdisk-fast-download-linux-amd64.zip
|
wget -O netdisk-fast-download.zip https://github.com/qaiu/netdisk-fast-download/releases/download/v3.0.2/netdisk-fast-download-bin.zip
|
||||||
unzip netdisk-fast-download.zip
|
unzip netdisk-fast-download-bin.zip
|
||||||
cd netdisk-fast-download
|
cd netdisk-fast-download
|
||||||
bash service-install.sh
|
bash service-install.sh
|
||||||
```
|
```
|
||||||
@@ -544,22 +544,11 @@ Core模块集成Vert.x实现类似spring的注解式路由API
|
|||||||
</picture>
|
</picture>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
## **免责声明**
|
||||||
|
- 用户在使用本项目时,应自行承担风险,并确保其行为符合当地法律法规。开发者不对用户因使用本项目而导致的任何后果负责。
|
||||||
|
|
||||||
## **声明**
|
## 支持该项目
|
||||||
|
开源不易,用爱发电,本项目长期维护如果觉得有帮助, 可以请作者喝杯咖啡, 感谢支持
|
||||||
- 本项目**仅供个人学习与技术交流使用**,请勿用于商业用途或大规模滥用。
|
|
||||||
- 所用接口均来自各网盘**官方开放平台**、官方公开接口及**已知开源项目**,仅解析用户主动提供的分享链接,**不涉及破解或绕过版权保护**。
|
|
||||||
- 本项目**相当于自动化程序代替用户发起请求**,**不会提升或绕过任何会员权限**,也**不会突破网盘的限速策略**;我们**鼓励用户开通官方 VIP/SVIP**以获得更好的下载与加速体验。
|
|
||||||
- 使用者应遵守各网盘服务商的**用户协议与使用条款**,以及所在地区的**法律法规**,违反所产生的后果自行承担。
|
|
||||||
- **高频调用可能触发网盘风控**,导致**账号限流、封禁**或**来源 IP 被屏蔽**,请合理控制请求频率,避免高并发与批量请求。
|
|
||||||
- 网盘接口调整、风控策略变更等因素可能导致功能失效,本项目**不对可用性与稳定性作任何担保**。
|
|
||||||
- 开发者**不对**使用本项目产生的**任何直接或间接损失**(账号封禁、数据丢失、法律纠纷等)**承担责任**。
|
|
||||||
- 开发者保留**随时修改本免责声明**的权利,恕不另行通知。
|
|
||||||
- **下载、部署或使用本项目,即视为您已阅读并接受上述全部条款。**
|
|
||||||
|
|
||||||
|
|
||||||
## 赞助该项目
|
|
||||||
开源不易,用爱发电,本项目长期维护如果觉得有帮助, 可以请开发者[喝杯咖啡](https://blog.qaiu.top/archives/da-shang-zhuan-yong), 感谢支持。
|
|
||||||
|
|
||||||
本项目的服务器由林枫云提供赞助<br>
|
本项目的服务器由林枫云提供赞助<br>
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -377,20 +377,39 @@ public abstract class PanBase implements IPanTool, Closeable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
// 上游响应体可能来自内网探测目标或非JSON内容,仅写日志,避免经 HTTP 500 回传给调用方
|
||||||
if ("gzip".equalsIgnoreCase(contentEncoding)) {
|
if ("gzip".equalsIgnoreCase(contentEncoding)) {
|
||||||
// gzip解压失败,记录错误
|
log.error("上游响应gzip解压或JSON解析失败: {}", e.getMessage());
|
||||||
log.error("响应gzip解压或JSON解析失败: {}", e.getMessage());
|
|
||||||
fail("响应gzip解压或JSON解析失败: {}", e.getMessage());
|
|
||||||
} else {
|
} else {
|
||||||
// 上游响应体可能来自内网探测目标,仅写日志,避免经 HTTP 500 回传给调用方
|
log.error("上游响应格式异常(非JSON): {}", responseBodyPreview(res));
|
||||||
String bodyPreview = responseBodyPreview(res);
|
|
||||||
log.error("解析失败: json格式异常: {}", bodyPreview);
|
|
||||||
fail("解析失败: json格式异常");
|
|
||||||
}
|
}
|
||||||
|
fail("上游响应格式异常");
|
||||||
return JsonObject.of();
|
return JsonObject.of();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 尝试将响应体解析为 JsonObject,失败时静默返回 null(不调用 fail())。
|
||||||
|
* 适用于版本探测等场景:响应可能是 HTML,此时不应立即终止解析流程。
|
||||||
|
*
|
||||||
|
* @param res HttpResponse
|
||||||
|
* @return JsonObject,若响应体不是合法 JSON 则返回 null
|
||||||
|
*/
|
||||||
|
protected JsonObject tryParseJson(HttpResponse<?> res) {
|
||||||
|
String contentEncoding = res.getHeader("Content-Encoding");
|
||||||
|
try {
|
||||||
|
if ("gzip".equalsIgnoreCase(contentEncoding)) {
|
||||||
|
String decompressed = decompressGzip((Buffer) res.body());
|
||||||
|
return new JsonObject(decompressed);
|
||||||
|
} else {
|
||||||
|
return res.bodyAsJsonObject();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.debug("响应体不是合法JSON,跳过: {}", e.getMessage());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* body To text的封装, 会自动处理异常, 会自动解压gzip
|
* body To text的封装, 会自动处理异常, 会自动解压gzip
|
||||||
* @param res HttpResponse
|
* @param res HttpResponse
|
||||||
|
|||||||
@@ -81,18 +81,15 @@ public class CeTool extends PanBase {
|
|||||||
// 禁止跟随重定向:assertPublicHost 只校验初始 host,自动 30x 会绕过 SSRF 防护
|
// 禁止跟随重定向:assertPublicHost 只校验初始 host,自动 30x 会绕过 SSRF 防护
|
||||||
clientNoRedirects.getAbs(pingUrlV4).send().onSuccess(res -> {
|
clientNoRedirects.getAbs(pingUrlV4).send().onSuccess(res -> {
|
||||||
if (res.statusCode() == 200) {
|
if (res.statusCode() == 200) {
|
||||||
try {
|
// 使用 tryParseJson 而非 asJson,避免非JSON响应(如HTML)提前终止整个解析流程
|
||||||
JsonObject json = asJson(res);
|
JsonObject json = tryParseJson(res);
|
||||||
// v4 ping 成功且返回有效JSON,使用 Ce4Tool
|
// v4 ping 成功且返回有效JSON,使用 Ce4Tool
|
||||||
if (json != null && !json.isEmpty()) {
|
if (json != null && !json.isEmpty()) {
|
||||||
log.debug("检测到Cloudreve 4.x (通过v4 ping)");
|
log.debug("检测到Cloudreve 4.x (通过v4 ping)");
|
||||||
delegateToCe4Tool();
|
delegateToCe4Tool();
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
// JSON解析失败,继续尝试 v3
|
|
||||||
log.debug("v4 ping返回非JSON响应,尝试v3");
|
|
||||||
}
|
}
|
||||||
|
log.debug("v4 ping返回非JSON响应,尝试v3");
|
||||||
}
|
}
|
||||||
// v4 ping失败或返回非JSON,尝试 v3
|
// v4 ping失败或返回非JSON,尝试 v3
|
||||||
tryV3Ping(baseUrl, key, pwd);
|
tryV3Ping(baseUrl, key, pwd);
|
||||||
@@ -111,18 +108,15 @@ public class CeTool extends PanBase {
|
|||||||
|
|
||||||
clientNoRedirects.getAbs(pingUrlV3).send().onSuccess(res -> {
|
clientNoRedirects.getAbs(pingUrlV3).send().onSuccess(res -> {
|
||||||
if (res.statusCode() == 200) {
|
if (res.statusCode() == 200) {
|
||||||
try {
|
// 使用 tryParseJson 而非 asJson,避免非JSON响应(如HTML)提前终止整个解析流程
|
||||||
JsonObject json = asJson(res);
|
JsonObject json = tryParseJson(res);
|
||||||
// v3 ping 成功且返回有效JSON,进一步验证是否为 v3
|
// v3 ping 成功且返回有效JSON,进一步验证是否为 v3
|
||||||
if (json != null && !json.isEmpty()) {
|
if (json != null && !json.isEmpty()) {
|
||||||
// 尝试调用 v3 share API 来确认
|
// 尝试调用 v3 share API 来确认
|
||||||
verifyV3AndParse(baseUrl, key, pwd);
|
verifyV3AndParse(baseUrl, key, pwd);
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
// JSON解析失败,不是Cloudreve盘
|
|
||||||
log.debug("v3 ping返回非JSON响应,不是Cloudreve盘");
|
|
||||||
}
|
}
|
||||||
|
log.debug("v3 ping返回非JSON响应,不是Cloudreve盘");
|
||||||
}
|
}
|
||||||
// v3 ping失败,不是Cloudreve盘
|
// v3 ping失败,不是Cloudreve盘
|
||||||
log.debug("v3 ping失败,尝试下一个解析器");
|
log.debug("v3 ping失败,尝试下一个解析器");
|
||||||
|
|||||||
@@ -1156,7 +1156,6 @@ export default {
|
|||||||
this.password = shortInfo.pwd
|
this.password = shortInfo.pwd
|
||||||
}
|
}
|
||||||
this.$message.success(`已识别短格式并自动转换,网盘类型: ${shortInfo.name}`)
|
this.$message.success(`已识别短格式并自动转换,网盘类型: ${shortInfo.name}`)
|
||||||
this.updateDirectLink()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1169,7 +1168,6 @@ export default {
|
|||||||
this.password = pwd
|
this.password = pwd
|
||||||
}
|
}
|
||||||
this.$message.success(`已从文本中识别到 ${linkInfo.name} 分享链接`)
|
this.$message.success(`已从文本中识别到 ${linkInfo.name} 分享链接`)
|
||||||
this.updateDirectLink()
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -1184,6 +1182,7 @@ export default {
|
|||||||
clearResults() {
|
clearResults() {
|
||||||
this.parseResult = {}
|
this.parseResult = {}
|
||||||
this.downloadUrl = null
|
this.downloadUrl = null
|
||||||
|
this.directLink = ''
|
||||||
this.markdownText = ''
|
this.markdownText = ''
|
||||||
this.showQRCode = false
|
this.showQRCode = false
|
||||||
this.statisticsData = {}
|
this.statisticsData = {}
|
||||||
@@ -1327,8 +1326,10 @@ export default {
|
|||||||
const directoryResult = await this.callAPI('/v2/getFileList', params)
|
const directoryResult = await this.callAPI('/v2/getFileList', params)
|
||||||
this.directoryData = directoryResult.data || []
|
this.directoryData = directoryResult.data || []
|
||||||
this.showDirectoryTree = true
|
this.showDirectoryTree = true
|
||||||
// 自动赋值分享链接
|
// 目录解析成功后,将目录落地页作为智能直链
|
||||||
this.showListLink = `${this.baseUrl}/showList?url=${encodeURIComponent(this.link)}`
|
const listUrl = `${this.baseUrl}/showList?url=${encodeURIComponent(this.link)}`
|
||||||
|
this.showListLink = listUrl
|
||||||
|
this.directLink = listUrl
|
||||||
|
|
||||||
this.$message.success(`目录解析成功!共找到 ${this.directoryData.length} 个文件/文件夹`)
|
this.$message.success(`目录解析成功!共找到 ${this.directoryData.length} 个文件/文件夹`)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -1427,7 +1428,6 @@ export default {
|
|||||||
if (shortInfo.link !== this.link || shortInfo.pwd !== this.password) {
|
if (shortInfo.link !== this.link || shortInfo.pwd !== this.password) {
|
||||||
this.password = shortInfo.pwd
|
this.password = shortInfo.pwd
|
||||||
this.link = shortInfo.link
|
this.link = shortInfo.link
|
||||||
this.updateDirectLink()
|
|
||||||
if (!this.hasClipboardSuccessTip) {
|
if (!this.hasClipboardSuccessTip) {
|
||||||
this.$message.success(`自动识别分享成功, 网盘类型: ${shortInfo.name}; 分享URL ${this.link}; 分享密码: ${this.password || '空'}`)
|
this.$message.success(`自动识别分享成功, 网盘类型: ${shortInfo.name}; 分享URL ${this.link}; 分享密码: ${this.password || '空'}`)
|
||||||
this.hasClipboardSuccessTip = true
|
this.hasClipboardSuccessTip = true
|
||||||
@@ -1446,8 +1446,6 @@ export default {
|
|||||||
if (linkInfo.link !== this.link || pwd !== this.password) {
|
if (linkInfo.link !== this.link || pwd !== this.password) {
|
||||||
this.password = pwd
|
this.password = pwd
|
||||||
this.link = linkInfo.link
|
this.link = linkInfo.link
|
||||||
// 更新智能直链(包含认证参数)
|
|
||||||
this.updateDirectLink()
|
|
||||||
// 聚焦期间只提示一次
|
// 聚焦期间只提示一次
|
||||||
if (!this.hasClipboardSuccessTip) {
|
if (!this.hasClipboardSuccessTip) {
|
||||||
this.$message.success(`自动识别分享成功, 网盘类型: ${linkInfo.name}; 分享URL ${this.link}; 分享密码: ${this.password || '空'}`)
|
this.$message.success(`自动识别分享成功, 网盘类型: ${linkInfo.name}; 分享URL ${this.link}; 分享密码: ${this.password || '空'}`)
|
||||||
|
|||||||
Reference in New Issue
Block a user