web-dev-qa-db-ja.com

ユーザースクリプトでXMLHttpRequestを使用して画像をダウンロードする

まず最初に、ここに同じタイトルの 質問 がありますSOしかし、私が探しているものではなく、完全な答えもありません。

だから私の質問です。たとえば、画像にリンクするこのURLがあるとします。

https://fbcdn-photos-a.akamaihd.net/hphotos-ak-ash4/299595_10150290138650735_543370734_8021370_355110168_n.jpg

このパラメータを入力したら、?dl=1 URLの最後までダウンロード可能になります。

https://fbcdn-photos-a.akamaihd.net/hphotos-ak-ash4/299595_10150290138650735_543370734_8021370_355110168_n.jpg?dl=1

ユーザースクリプトを使用してこのタスクを実行しようとしています。そのため、XMLHttpRequestを使用しました。

var url = "https://fbcdn-photos-a.akamaihd.net/hphotos-ak-ash4/299595_10150290138650735_543370734_8021370_355110168_n.jpg?dl=1";

var request = new XMLHttpRequest();  
request.open("GET", url, false);   
request.send(null);  

if (request.status === 200) 
{  
    alert(request.statusText);
}

これが fiddle です。

しかし、それは機能しません。

16
Isuru

XMLHttpRequestはクロスドメインでは機能しませんが、これはuserscriptであるため、ChromeはGM_xmlhttpRequest()をユーザースクリプトでのみサポートするようになりました。

このようなものが動作するはずです。非同期であることに注意してください:

_GM_xmlhttpRequest ( {
    method:         'GET',
    url:            'https://fbcdn-photos-a.akamaihd.net/hphotos-ak-ash4/299595_10150290138650735_543370734_8021370_355110168_n.jpg?dl=1',
    onload:         function (responseDetails) {
                        alert(responseDetails.statusText);
                    }
} );
_




実際の画像データを取得して使用することに関しては、それは解決するのに大きな苦痛です。

  • Firefoxでは新しい_.responseType = "blob";_機能を使用できますが、 Chromeはまだサポートしていません

  • ChromeまたはFirefoxでは、同じドメインに対してのみ、新しい XHR2 を次のように使用できます。
    jsBinで動作を確認してください。

    _BlobBuilder             = window.MozBlobBuilder || window.WebKitBlobBuilder || window.BlobBuilder;
    
    var url                 = "http://jsbin.com/images/gear.png";
    var request             = new XMLHttpRequest();
    request.open ("GET", url, false);
    request.responseType    = "arraybuffer";
    request.send (null);
    
    if (request.status === 200) {
        var bb              = new BlobBuilder ();
        bb.append (request.response); // Note: not request.responseText
    
        var blob            = bb.getBlob ('image/png');
        var reader          = new FileReader ();
        reader.onload       = function (zFR_Event) {
            $("body").prepend ('<p>New image: <img src="' + zFR_Event.target.result + '"></p>')
        };
    
        reader.readAsDataURL (blob);
    }
    _


  • 残念ながら、GM_xmlhttpRequest()responseTypeの設定を(まだ)サポートしていません。


したがって、GMスクリプトまたはユーザースクリプトアプリケーションの場合、 "Javascript Hacks:Using XHR to load binary data" のようなカスタムbase64エンコードスキームを使用する必要があります。

スクリプトコードは次のようになります。

_var imgUrl              = "http://jsbin.com/images/gear.png";

GM_xmlhttpRequest ( {
    method:         'GET',
    url:            imgUrl,
    onload:         function (respDetails) {
                        var binResp     = customBase64Encode (respDetails.responseText);

                        /*-- Here, we just demo that we have a valid base64 encoding
                            by inserting the image into the page.
                            We could just as easily AJAX-off the data instead.
                        */
                        var zImgPara    = document.createElement ('p');
                        var zTargetNode = document.querySelector ("body *"); //1st child

                        zImgPara.innerHTML = 'Image: <img src="data:image/png;base64,'
                                           + binResp + '">';
                        zTargetNode.parentNode.insertBefore (zImgPara, zTargetNode);
                    },
    overrideMimeType: 'text/plain; charset=x-user-defined'
} );


function customBase64Encode (inputStr) {
    var
        bbLen               = 3,
        enCharLen           = 4,
        inpLen              = inputStr.length,
        inx                 = 0,
        jnx,
        keyStr              = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
                            + "0123456789+/=",
        output              = "",
        paddingBytes        = 0;
    var
        bytebuffer          = new Array (bbLen),
        encodedCharIndexes  = new Array (enCharLen);

    while (inx < inpLen) {
        for (jnx = 0;  jnx < bbLen;  ++jnx) {
            /*--- Throw away high-order byte, as documented at:
              https://developer.mozilla.org/En/Using_XMLHttpRequest#Handling_binary_data
            */
            if (inx < inpLen)
                bytebuffer[jnx] = inputStr.charCodeAt (inx++) & 0xff;
            else
                bytebuffer[jnx] = 0;
        }

        /*--- Get each encoded character, 6 bits at a time.
            index 0: first  6 bits
            index 1: second 6 bits
                        (2 least significant bits from inputStr byte 1
                         + 4 most significant bits from byte 2)
            index 2: third  6 bits
                        (4 least significant bits from inputStr byte 2
                         + 2 most significant bits from byte 3)
            index 3: forth  6 bits (6 least significant bits from inputStr byte 3)
        */
        encodedCharIndexes[0] = bytebuffer[0] >> 2;
        encodedCharIndexes[1] = ( (bytebuffer[0] & 0x3) << 4)   |  (bytebuffer[1] >> 4);
        encodedCharIndexes[2] = ( (bytebuffer[1] & 0x0f) << 2)  |  (bytebuffer[2] >> 6);
        encodedCharIndexes[3] = bytebuffer[2] & 0x3f;

        //--- Determine whether padding happened, and adjust accordingly.
        paddingBytes          = inx - (inpLen - 1);
        switch (paddingBytes) {
            case 1:
                // Set last character to padding char
                encodedCharIndexes[3] = 64;
                break;
            case 2:
                // Set last 2 characters to padding char
                encodedCharIndexes[3] = 64;
                encodedCharIndexes[2] = 64;
                break;
            default:
                break; // No padding - proceed
        }

        /*--- Now grab each appropriate character out of our keystring,
            based on our index array and append it to the output string.
        */
        for (jnx = 0;  jnx < enCharLen;  ++jnx)
            output += keyStr.charAt ( encodedCharIndexes[jnx] );
    }
    return output;
}
_
22
Brock Adams

別のドメインにあるためブロックされているXHRを使用してリソースをリクエストしようとしています。 XHRを使用してクロスドメインメッセージングにCORSを使用します。

4
Klemen Slavič

Krof Drakulaは正解です。別のドメインから画像を読み込むことはできませんが、本当にこれを行う必要がありますか? imgタグを作成して追加し、それがロードされるのを待つことができます(jQuery load()など)。

var img = document.createElement( 'img' );
img.setAttribute( 'src', url );
document.getElementsByTagName('body')[0].appendChild( img );
0
Daniel J F

最近のブラウザには Blob オブジェクトがあります:

GM_xmlhttpRequest({
  method: "GET",
  url: url,
  headers: { referer: url, Origin: url },
  responseType: 'blob',
  onload: function(resp) {
    var img = document.createElement('img');
    img.src = window.URL.createObjectURL(resp.response);
    document.body.appendChild(img);
  }
});

headers paramはリファラーを設定するため、リファラーがロックされた画像をロードできます。

0
ariel