Greasy Fork is available in English.

百度云直接下载

直接下载百度云的文件,可以避免下载文件时调用云管家;只支持单个文件,不支持文件夹和多文件下载

Versión del día 4/10/2016. Echa un vistazo a la versión más reciente.

// ==UserScript==
// @name         百度云直接下载
// @namespace    undefined
// @version      0.2
// @description  直接下载百度云的文件,可以避免下载文件时调用云管家;只支持单个文件,不支持文件夹和多文件下载
// @author       Roger Zhu
// @match        http://pan.baidu.com/*
// @match        https://pan.baidu.com/*
// @require      http://code.jquery.com/jquery-latest.js
// @run-at       document-end
// @grant        none
// ==/UserScript==
var $ = $ || window.$;

(function() {
    'use strict';
    var yunData,sign,fidlist=null,timestamp,bdstoken,fileid=null,logid,downloadLink;
    var panAPIUrl = "https://pan.baidu.com/api/";
    var restAPIUrl1 = "https://pcs.baidu.com/rest/2.0/pcs/";
    var restAPIUrl2 = "https://d.pcs.baidu.com/rest/2.0/pcs/";
    
    initParams();
    addButton();
    createIframe();
    console.log('Baidu Yun Helper load successful!');
    
    function initParams(){
        yunData = window.yunData;
        sign = getSign();
        timestamp = getTimestamp();
        bdstoken = getBDStoken();
        logid = getLogid();
    }
    
    //添加下载按钮
    function addButton(){
        var $dropdownbutton = $('<span class="g-dropdown-button"></span>');
        var $dropdownbutton_a = $('<a class="g-button" data-button-id="b200" data-button-index="200" href="javascript:void(0);"></a>');
        var $dropdownbutton_a_span = $('<span class="g-button-right"><em class="icon icon-download-gray" title="百度云下载助手"></em><span class="text" style="width: auto;">下载助手</span></span>');
        var $dropdownbutton_span = $('<span class="menu" style="width:auto"></span>');
        
        var $panAPIDownloadButton = $('<a data-menu-id="b-menu201" class="g-button-menu" href="javascript:void(0);">直接下载</a>');
        var $restAPIDownloadButton1 = $('<a data-menu-id="b-menu202" class="g-button-menu" href="javascript:void(0);">API下载一</a>');
        var $restAPIDownloadButton2 = $('<a data-menu-id="b-menu203" class="g-button-menu" href="javascript:void(0);">API下载二</a>');
        
        $dropdownbutton_span.append($panAPIDownloadButton).append($restAPIDownloadButton1).append($restAPIDownloadButton2);
        $dropdownbutton_a.append($dropdownbutton_a_span);
        $dropdownbutton.append($dropdownbutton_a).append($dropdownbutton_span);
        
        $dropdownbutton.hover(function(){
            $dropdownbutton.toggleClass('button-open');
        });
        
        $panAPIDownloadButton.click(panAPIDownloadClick);
        $restAPIDownloadButton1.click(restAPIDownloadClick1);
        $restAPIDownloadButton2.click(restAPIDownloadClick2);
        
        $($('div.list-header-operate div').get(1)).append($dropdownbutton);
    }
    
    function panAPIDownloadClick(){
        console.log('PAN API download button clicked.');
        
        if(!checkSelectItem())
            return;
        
        fileid = getSelectFileId();

        if (fileid === null) {
            return;
        }

        fidlist = getFidList(fileid);

        if (fidlist.length === 0) {
            alert("获取文件ID失败,请重试!");
            return;
        }

        fidlist = "["+fidlist+"]";

        downloadLink = getDownloadLinkWithPanAPI(fidlist);
        execDownload(downloadLink);
    }
    
    function restAPIDownloadClick1(){
        console.log("REST API download 1 button clicked.");
        if(!checkSelectItem())
            return;
        downloadLink = getDownloadLinkWithRESTAPI1();
        execDownload(downloadLink);
    }
    
    function restAPIDownloadClick2(){
        console.log("REST API download 1 button clicked.");
        if(!checkSelectItem())
            return;
        downloadLink = getDownloadLinkWithRESTAPI2();
        execDownload(downloadLink);
    }
    
    function checkSelectItem(){
        var $dd = $('div.list-view dd.item-active');
        if ($dd.length === 0) {
            alert("没有选中文件!");
            return false;
        } else if ($dd.length>1){
            alert("不要选中多个文件,只支持单个下载!");
            return false;
        }
        var $div = $($dd[0]).children('div');
        var type = $($div[0]).attr('class').split(" ");
        if(type[1] == "dir-small"){
            alert("不支持目录下载!");
            return false;
        }
        return true;
    }

    function getSign(){
        var signFnc;
        try{
            signFnc = new Function("return " + yunData.sign2)();
        } catch(e){
            throw new Error(e.message);
        }
        return base64Encode(signFnc(yunData.sign5,yunData.sign1));
    }

    //获取当前目录
    function getDir(){
        var url = window.location.href;
        return decodeURIComponent(url.substring(url.lastIndexOf('=')+1));
    }
    
    function getFileName(){
        var fileid = null;
        var $a = $('div.list-view dd.item-active div.file-name a.filename');
        var filename = $a[0].text;
        return filename;
    }

    //获取当前目录的文件列表
    function getFileList(dir){
        var filelist = null;
        var listUrl = panAPIUrl + "list";
        var params = {
            dir:dir,
            bdstoken:bdstoken,
            logid:logid,
            num:100,
            order:'size',
            desc:0,
            clienttype:0,
            showempty:'0',
            web:1,
            page:1,
            channel:'chunlei',
            appid:250528
        };
        $.ajax({
            url:listUrl,
            async:false,
            method:'GET',
            data:params,
            success:function(result){
                filelist = result;
            }
        });
        return filelist;
    }

    //获取选中文件的fileid
    function getSelectFileId(){
        var dir = getDir();
        var filename = getFileName();
        if(filename === null)
            return null;
        var filelist = getFileList(dir);
        
        console.log("filename:"+filename);

        if(filelist === null || filelist.errno !== 0){
            alert("获取文件列表失败,请重试!");
            return null;
        } else {
            for(var i=0;i<filelist.list.length;i++){
                if (filelist.list[i].server_filename === filename){
                    fileid = filelist.list[i].fs_id;
                }
            }
        }
        return fileid;
    }

    function getFidList(fileid){
        var list = [];

        if(fileid !== null){
            list.push(fileid);
        }

        return list;
    }

    function getTimestamp(){
        return yunData.timestamp;
    }

    function getBDStoken(){
        return yunData.MYBDSTOKEN;
    }

    function getLogid(){
        var name = "BAIDUID";
        function getCookie(e) {
            var o, t;
            var n = window.document,c=window.decodeURI;
            return n.cookie.length > 0 && (o = n.cookie.indexOf(e + "="),-1 != o) ? (o = o + e.length + 1,t = n.cookie.indexOf(";", o),-1 == t && (t = n.cookie.length),c(n.cookie.substring(o, t))) : "";
        }
        var u = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/~!@#¥%……&";
        var d = /[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g;
        var f = String.fromCharCode;
        function l(e){
            if (e.length < 2) {
                var n = e.charCodeAt(0);
                return 128 > n ? e : 2048 > n ? f(192 | n >>> 6) + f(128 | 63 & n) : f(224 | n >>> 12 & 15) + f(128 | n >>> 6 & 63) + f(128 | 63 & n);
            }
            var n = 65536 + 1024 * (e.charCodeAt(0) - 55296) + (e.charCodeAt(1) - 56320);
            return f(240 | n >>> 18 & 7) + f(128 | n >>> 12 & 63) + f(128 | n >>> 6 & 63) + f(128 | 63 & n);
        }
        function g(e){
            return (e + "" + Math.random()).replace(d, l);
        }
        function m(e){
            var n = [0, 2, 1][e.length % 3];
            var t = e.charCodeAt(0) << 16 | (e.length > 1 ? e.charCodeAt(1) : 0) << 8 | (e.length > 2 ? e.charCodeAt(2) : 0);
            var o = [u.charAt(t >>> 18), u.charAt(t >>> 12 & 63), n >= 2 ? "=" : u.charAt(t >>> 6 & 63), n >= 1 ? "=" : u.charAt(63 & t)];
            return o.join("");
        }
        function h(e){
            return e.replace(/[\s\S]{1,3}/g, m);
        }
        function p(){
            return h(g((new Date()).getTime()));
        }
        function w(e,n){
            return n ? p(String(e)).replace(/[+\/]/g, function(e) {
                return "+" == e ? "-" : "_";
            }).replace(/=/g, "") : p(String(e));
        }
        return w(getCookie(name));
    }

    //获取下载地址。这个地址不是直接下载地址,访问这个地址会返回302,response header中的location才是真实下载地址
    //暂时没有找到提取方法
    function getDownloadLinkWithPanAPI(fidlist){
        var downloadUrl = panAPIUrl + "download";
        var link = null;
        var params= {
            sign:sign,
            timestamp:timestamp,
            fidlist:fidlist,
            type:'dlink',
            channel:'chunlei',
            web:1,
            app_id:250528,
            bdstoken:bdstoken,
            logid:logid,
            clienttype:0
        };
        $.ajax({
            url:downloadUrl,
            async:false,
            method:'GET',
            data:params,
            success:function(result){
                link = result.dlink[0].dlink;
            }
        });
        return link;
    }

    function getDownloadLinkWithRESTAPI1(){
        var path = getDir();
        var filename = getFileName();
        
        var link = restAPIUrl1 + 'file?method=download&app_id=250528&path=' + path + '/' + filename;
        return link;
    }
    
    function getDownloadLinkWithRESTAPI2(){
        var path = getDir();
        var filename = getFileName();
        
        var link = restAPIUrl2 + 'file?method=download&app_id=250528&path=' + path + '/' + filename;
        return link;
    }
    
    function execDownload(link){
        console.log("download link:"+link);
        $('#helperdownloadiframe').attr('src',link);
    }

    function createIframe(){
        var $div = $('<div class="helper-hide" style="padding:0;margin:0;display:block"></div>');
        var $iframe = $('<iframe src="javascript:void(0)" id="helperdownloadiframe" style="display:none"></iframe>');
        $div.append($iframe);
        $('body').append($div);

    }

    function base64Encode(t){
        var a, r, e, n, i, s, o = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
        for (e = t.length,r = 0,a = ""; e > r; ) {
            if (n = 255 & t.charCodeAt(r++),r == e) {
                a += o.charAt(n >> 2);
                a += o.charAt((3 & n) << 4);
                a += "==";
                break;
            }
            if (i = t.charCodeAt(r++),r == e) {
                a += o.charAt(n >> 2);
                a += o.charAt((3 & n) << 4 | (240 & i) >> 4);
                a += o.charAt((15 & i) << 2);
                a += "=";
                break;
            }
            s = t.charCodeAt(r++);
            a += o.charAt(n >> 2);
            a += o.charAt((3 & n) << 4 | (240 & i) >> 4);
            a += o.charAt((15 & i) << 2 | (192 & s) >> 6);
            a += o.charAt(63 & s);
        }
        return a;
    }
    function testAjax(url){
        $.ajax({
            url:url,
            method:'GET',
            async:true,
            xhrFields:{
                withCredentials: true
            },
            success:function(data,textStatus,xhr){
                console.log(xhr);
            },
            error:function(xhr,textStatus,error){
                console.log(xhr);
            }
        });
    }
    function testFetch(url){
        var request = new Request(url,{
            method:'GET',
            mode:'no-cors',//使用no-cors会正常提交请求,浏览器会在后台用fetch获取文件;使用cors,访问302重定向后的地址会产生错误,原因是提交的请求header里面origin为null
            redirect: 'follow',
            credentials: 'include'
        });
        fetch(request).then(function(response){
            console.log("response:");
            console.log(response);
        });
    }
    function testXHR(url){
        var xhr = new XMLHttpRequest();
        xhr.withCredentials = true;
        xhr.onload = function(e){
            console.log("onload:");
            console.log(this);
            console.log(e);
        };
        xhr.onreadystatechange = function(e){
            console.log("onreadystatechange:");
            console.log(this);
            console.log(e);
        };

        //xhr.open("GET",url,true);
        //xhr.send();

        xhr.open('HEAD',url);
        xhr.send(null);
    }
})();