此脚本不应直接安装,它是一个供其他脚本使用的外部库。如果您需要使用该库,请在脚本元属性加入:// @require https://update.cn-greasyfork.org/scripts/515674/1518464/MyDownloader.js
您需要先安装一款用户样式管理器扩展(如 Stylus)后才能安装此样式。
您需要先安装一款用户样式管理器扩展(如 Stylus)后才能安装此样式。
您需要先安装一款用户样式管理器扩展(如 Stylus)后才能安装此样式。
您需要先安装一款用户样式管理器扩展后才能安装此样式。
您需要先安装一款用户样式管理器扩展后才能安装此样式。
您需要先安装一款用户样式管理器扩展后才能安装此样式。
(我已经安装了用户样式管理器,让我安装!)
// ==UserScript==
// @name MyDownloader
// @version 2025.01.11
// @description 包含多种下载方法的下载库
// @author You
// @grant none
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_deleteValue
// @grant GM_download
// @require https://update.greasyfork.org/scripts/480132/1476440/Get_all_img_Library.js
// @require https://update.greasyfork.org/scripts/522187/1511410/Kquery.js
// ==/UserScript==
// 2025.01.07 更新了download text
// 2025.01.07.02 更新了download text(src,name)
// 2025.01.07.03 修复了download text(src,name)没有传入name的bug
/**
* 包含多种下载方法的下载类
* @example
const downloader = new Downloader();
downloader.Download_img(imgs);
*/
function Downloader(){
let downloading = 0;
let downloaded = [];
let downloadError = [];
let imgs = null;
let maxDownloadingCounts = 10;
let timeout = null;
let AllComplete = null;
let OneSuccess = null;
let OneError = null;
let downloadType = ""
/**
* @example Download_img(imgs)
*/
this.Download_img = async (imgs)=>{
if(downloadType==""){
await Test_downloadType(imgs.eq(0));
}
Set_download(imgs)
console.log(downloadType);
if(downloadType=="GM_download"){
Donwload_img_by_GM();
}else if(downloadType=="atag"){
Donwload_img_by_atag();
}else if(downloadType=="blob"){
Donwload_img_by_blob();
}else{
alert("no this donwload type");
}
}
/**
* @example downloadType.value = "GM_download" || "atag" || "blob"
*/
this.downloadType = {get value(){return downloadType;},set value(v){downloadType = v;}};
/**
* @example maxDownloadingCounts.value = 100
*/
this.maxDownloadingCounts = {get value(){return maxDownloadingCounts;},set value(v){maxDownloadingCounts = v}};
/**
* @example timeout.value = 1000
*/
this.timeout = {get value(){return timeout;},set value(v){timeout = v}};
/**
* @example OneSuccess((success_img)=>{...})
*/
this.OneSuccess = foo=>OneSuccess = foo;
/**
* @example OneError((error_img)=>{...})
*/
this.OneError = foo=>OneError = foo;
/**
* @example AllComplete(()=>{...})
*/
this.AllComplete = foo=>AllComplete = foo;
this.Test_downloadType = (img)=>{Test_downloadType(img);}
async function Test_downloadType(img){
return new Promise((resolve)=>{
let timeout = 3000;
let isOk = false;
GM_download({
url:img[0].src,
name:"test.png",
onload:()=>{isOk = true;downloadType = "GM_download";resolve()},
})
setTimeout(()=>{
if(!isOk){downloadType = "atag";}
resolve()
},timeout)
})
}
this.Set_download = (iimgs)=>{Set_download(iimgs);}
function Set_download(iimgs){
downloaded = [];
downloading = 0;
downloadError = [];
imgs = iimgs;
}
this.Donwload_img_by_GM = ()=>{Donwload_img_by_GM();}
function Donwload_img_by_GM(){
if(!imgs || imgs.length == 0){alert("imgs is empty");return;}
async function Download_one(i){
if(i>=imgs.length){if(AllComplete){AllComplete()};return;}
if(downloading>=maxDownloadingCounts){setTimeout(()=>{Download_one(i)},1000);return;}
let name = '';
let src = '';
downloading++;
try{
await Check_and_get_nameAndsrc({img:imgs.eq(i),checkSrc:true})
.then((m)=>{
name = m.name;
src = m.src;
});
}catch(error){
console.log(error)
console.log('imgsrc is error:');
downloadError.push(i);
downloading--;
Download_one(i+1);
return;
}
console.log(name)
console.log(document.title)
let timeout = false;
setTimeout(() => {timeout = true;},10000);
const downimg = imgs.eq(i);
GM_download({
url:src,
name:name,
onload:function(){
downloaded.push(downimg);
downloading--;
if(window.GAIL.showmass){
window.GAIL.showmass((downloaded.length+downloadError.length)+"/"+imgs.length);
}
imgs.eq(i).remove();
if(OneSuccess){OneSuccess(downimg);}
},
onerror:function(){
downloading--;
downloadError.push(downimg);
if(OnError){OnError(downimg);}
},
onprogress:function(){
if(timeout){return false;}
}
});
setTimeout(function() {Download_one(i+1);}, 10);
}
Download_one(0);
}
this.Donwload_img_by_atag = (nowIsImgPage)=>{Donwload_img_by_atag(nowIsImgPage);}
async function Donwload_img_by_atag(nowIsImgPage) {
if (!nowIsImgPage) {
if(!imgs || imgs.length==0){alert("imgs is empty");return;}
GM_setValue("downloadName", document.title);
for (let i = 0; i < imgs.length; i++) {
GM_setValue("downloadType", "start");
let name;
let src;
await Check_and_get_nameAndsrc({img:imgs.eq(i),checkSrc:false})
.then((m)=>{
name = m.name;
src = m.src;
});
GM_setValue("downloadSrc", src);
let mi = new My_iframe();
let iframe;
await mi.Add_iframe(src).then(ifr=>iframe = ifr);
//const myWindow = window.open(src, '_blank');
await new Promise(resolve => {
const checkDownload = setInterval(() => {
if (GM_getValue("downloadType") === "end") {
resolve();
clearInterval(checkDownload);
}
}, 100);
});
$(iframe).remove();
OneSuccess(imgs.eq(i));
downloaded.push(imgs.eq(i));
window.GAIL.showmass((downloaded.length+downloadError.length)+"/"+imgs.length);
$(".mass_top").css({'font-size':'6vmin'});
}
AllComplete();
} else {
await Check_and_get_nameAndsrc({img:$("img"),checkSrc:true})
.then((m)=>{
let name = m.name;
let src = m.src;
$('<a></a>').attr({
'href': src,
'download': name,
})[0].click();
});
await new Promise(resolve => setTimeout(resolve, 1000));
GM_setValue("downloadType", "end");
window.close();
}
}
this.Listening_Download_by_atag = ()=>{
const locationHref = window.location.href;
const GM_downloadSrc = GM_getValue("downloadSrc");
if(!GM_downloadSrc){return;}
if(GM_downloadSrc == locationHref|| locationHref.indexOf(GM_downloadSrc)>=0 || GM_downloadSrc.indexOf(locationHref)>=0 ){
Donwload_img_by_atag(true);
}
}
this.Donwload_img_by_blob = ()=>{Donwload_img_by_blob();}
function Donwload_img_by_blob(){
if(!imgs || imgs.length==0){alert("imgs is empty");return;}
const obo = (i)=>{
if(i>=imgs.length){return;}
if(maxDownloadingCounts>1 && downloading >= maxDownloadingCounts){
setTimeout(function() {obo(i)}, 1000);
}
let src = imgs.eq(i).attr('big_src');
if(!src){src = imgs.eq(i).attr('src');}
const checkimg = imgs.eq(i);
downloading++;
UrlToBlob({url:src,timeout:timeout})
.then(blob=>{
Check_and_get_nameAndsrc({img:checkimg}).then(args=>{
const name = args.name;
let a = $('<a></a>').attr({
download:name,
href:blob
})
a[0].click();
downloaded.push(checkimg);
downloading--;
checkimg.attr('src',blob);
OneSuccess(checkimg);
})
if(maxDownloadingCounts==1){
obo(++i);
}else{
window.GAIL.showmass((downloaded.length+downloadError.length)+"/"+imgs.length);
}
})
.catch(er=>{
console.log(er);
downloadError.push(imgs.eq(i));
downloading--;
if(maxDownloadingCounts==1){
obo(++i);
}else{
window.GAIL.showmass((downloaded.length+downloadError.length)+"/"+imgs.length);
}
});
if(maxDownloadingCounts>1){
setTimeout(function() {obo(++i);}, 10);
}
}
obo(0);
}
/**
* @example Urls({url:url,timeout : 100})
*/
this.UrlToBlob = (args)=>{UrlToBlob(args);}
async function UrlToBlob(args) {
return new Promise((resolve,reject)=>{
if(!args.url){reject("no url");}
if(args.timeout){
const timeout = setTimeout(function() {reject("fetch timeout")}, args.timeout);
}
fetch(args.url)
.then(response => {
const contentLength = response.headers.get('Content-Length');
const total = parseInt(contentLength, 10);
let loaded = 0;
// 克隆响应以便分别读取流和获得 Blob
const clonedResponse = response.clone();
const reader = clonedResponse.body.getReader();
// 更新进度的函数
function updateProgress({ done, value }) {
if (done) {
return; // 如果读取完毕,直接返回
}
loaded += value.byteLength; // 累加已加载字节
const progress = (loaded / total) * 100; // 计算进度百分比
console.log(`Loading: ${progress.toFixed(2)}%`);
FetchShowProgress(progress);
// 继续读取下一块数据
return reader.read().then(updateProgress);
}
// 开始读取流以更新进度
return reader.read().then(updateProgress).then(() => {
// 完成后返回原始响应的 Blob
return response.blob();
});
})
.then(blob => {
const blobUrl = URL.createObjectURL(blob);
resolve(blobUrl);
})
.catch(error => {
console.error('Error caching video:', error);
reject(error);
});
});
}
this.FetchShowProgress = (pro)=>{FetchShowProgress(pro);}
function FetchShowProgress(pro){
if(this.maxDownloadingCounts==1 && this.imgs.length==1){
window.GAIL.showmass(pro);
$(".mass_top").css('font-size',"10vmin");
}
}
this.Check_and_get_nameAndsrc = (args)=>{Check_and_get_nameAndsrc(args);}
function Check_and_get_nameAndsrc(args){
return new Promise(async (resolve,reject)=>{
if(!args || !args.img){return reject();}
let src = args.img.attr('big_src');
if(!src){src = args.img.attr('src');}
if(!src){src = args.img.attr('small_src');}
if(!src){reject();}
//console.log("check:"+src)
if(args.checkSrc){
try{
await check_src_is_right(src);
}catch(error){
reject();
}
}
let ext = src.match(/\.jpg|\.png|\.webp|\.gif|\.bmp/g);
if(!ext){ext = '.png';}else{ext = ext[0];}
let name = args.img.attr('name');
if(!name){name = document.title + new Date().getTime() + ext;}
resolve({name:name,src:src});
});
}
this.check_src_is_right = (src)=>{check_src_is_right(src);}
function check_src_is_right(src){
return new Promise((resolve,reject)=>{
let iimg = new Image();
iimg.onload = function(){
if(this.width*this.height*this.naturalWidth*this.naturalHeight==0){reject();}else{resolve();}
}
iimg.onerror = function(){reject();}
iimg.src = src;
setTimeout(function() {reject();}, 2000);
})
}
function downloadText(text,name) {
// 创建 Blob 对象
var blob = new Blob([text], { type: "text/plain" });
// 创建下载链接
var url = URL.createObjectURL(blob);
// 创建下载按钮
var a = document.createElement("a");
a.href = url;
a.download = name?name:"downloaded_text"+new Date().getTime()+".txt"; // 文件名
document.body.appendChild(a);
// 模拟点击下载
a.click();
// 清理
window.URL.revokeObjectURL(url);
document.body.removeChild(a);
}
this.Download_to_text = (url,name)=>{downloadText(url,name);}
}
$(function(){
let dd = new Downloader()
dd.Listening_Download_by_atag()
})
window.Downloader = Downloader;