4

HTML5システムを使用して自分のWebサイトの画像を保存しようとしています。ローカル画像をクロムファイルシステムに保存する方法を示す例はたくさんありますが、WebURLとWebURLで画像を取得する方法が見つかりません。次に、それをHTML5ファイルシステムに保存します。

これは私のコードですが、間違っています。

        lib.ajax.get(file , function(xhr, data){
            if(xhr.status == 200){
                fs.root.getFile("test.jpg", {create: true}, function(fileEntry) {
                    // Create a FileWriter object for our FileEntry (log.txt).
                    fileEntry.createWriter(function(fileWriter) {
                        fileWriter.onwriteend = function(e) {
                            console.log('Write completed.');
                        };

                        fileWriter.onerror = function(e) {
                            console.log('Write failed: ' + e.toString());
                        };
                        // Create a new Blob and write it to log.txt.
                        var bb = new BlobBuilder(); // Note: window.WebKitBlobBuilder in Chrome 12.
                        bb.append(data);
                        fileWriter.write(bb.getBlob('image/jpeg'));
                        callback && callback("test.jpg");
                    }, errorHandler);

                }, errorHandler);
            }
        });
4

5 に答える 5

2

問題は、ブラウザーが xhr 応答データを UTF-8 として解析することです。したがって、ポイントは MimeType をオーバーライドすることです。

window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;

var xhr = new XMLHttpRequest();
var photoUrl = 'http://localhost:3000/image.jpg';
xhr.open('GET', photoUrl, true);

// This stops the browser from parsing the data as UTF-8:
xhr.overrideMimeType('text/plain; charset=x-user-defined');

function stringToBinary(response) {
  var byteArray = new Uint8Array(response.length);
  for (var i = 0; i < response.length; i++) {
    byteArray[i] = response.charCodeAt(i) & 0xff;
  }
  return byteArray
}

function onInitFs(fs) {
  xhr.onreadystatechange = function() {
    if (xhr.readyState == 4 && xhr.status == 200) {
      fs.root.getFile('image.jpg', {'create': true}, function(fileEntry) {
        fileEntry.createWriter(function(fileWriter) {
          fileWriter.onwriteend = function(event) {
            $('body').append('<img src="' + fileEntry.toURL() + '"/>');
          }

          buffer = stringToBinary(xhr.response);
          var blob = new Blob([ buffer ], { type: 'image/jpeg' } )

          fileWriter.write(blob);
        }, errorHandler );
      });
    }
  }
  xhr.send();
}

var errorHandler = function(err) {
  console.log(err);
}

$(function() {
  webkitStorageInfo.requestQuota(PERSISTENT, 5*1024*1024, function(grantedBytes) {
    requestFileSystem(PERSISTENT, grantedBytes, onInitFs, errorHandler)
  }, errorHandler)
})
于 2012-11-09T01:38:29.653 に答える
2

ここで私が使用する関数。Blob コンストラクターを使用するため、最新の Chrome (非推奨の BlobBuilder がない) で動作し、xhr.responseType の「blob」がない古い iOS 6 でも動作します。

コメントには、非推奨の BlobBuilder のコードも含まれています。

注意: XHR を使用しているため、CORS を有効にする必要があります。

window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
window.requestFileSystem(window.PERSISTENT, 2*1024*1024, onFileSystemSuccess, fail);


function onFileSystemSuccess(fileSystem) {
    fs = fileSystem;
    console.log('File system initialized');

    saveAsset('http://www.example-site-with-cors.com/test.png');
}


function saveAsset(url, callback, failCallback) {
    var filename = url.substring(url.lastIndexOf('/')+1);

    // Set callback when not defined
    if (!callback) {
        callback = function(cached_url) {
            console.log('download ok: ' + cached_url);
        };
    }
    if (!failCallback) {
        failCallback = function() {
            console.log('download failed');
        };
    }

    // Set lookupTable if not defined
    if (!window.lookupTable)
        window.lookupTable = {};

    // BlobBuilder shim
    // var BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder;

    var xhr = new XMLHttpRequest();
    xhr.open('GET', url, true);
    // xhr.responseType = 'blob';
    xhr.responseType = 'arraybuffer';

    xhr.addEventListener('load', function() {

        fs.root.getFile(filename, {create: true, exclusive: false}, function(fileEntry) {
            fileEntry.createWriter(function(writer) {

                writer.onwrite = function(e) {
                    // Save this file in the path to URL lookup table.
                    lookupTable[filename] = fileEntry.toURL();
                    callback(fileEntry.toURL());
                };

                writer.onerror = failCallback;

                // var bb = new BlobBuilder();
                var blob = new Blob([xhr.response], {type: ''});
                // bb.append(xhr.response);
                writer.write(blob);
                // writer.write(bb.getBlob());

            }, failCallback);
        }, failCallback);
    });

    xhr.addEventListener('error', failCallback);
    xhr.send();

    return filename;
}



function fail(evt) {
    console.log(evt.target.error.code);
}
于 2014-05-21T10:59:35.360 に答える
1

私はこれを行う方法を見つけます。

canvans.toDataURLを使用してデータ形式を転送します。

var img = new Image();
                var cvs = document.createElement('canvas');
                var ctx  = cvs.getContext("2d");
                img.src = file;
                img.onload = function(){
                    cvs.width = img.width;
                    cvs.height = img.height;
                    ctx.drawImage(img, 0, 0);
                    var imd = cvs.toDataURL(contentType[extname]);
                    var ui8a = convertDataURIToBinary(imd);
                    var bb = new BlobBuilder();
                    bb.append(ui8a.buffer);
                    fs.root.getFile(path, {create: true}, function(fileEntry) {
                        // Create a FileWriter object for our FileEntry (log.txt).
                        fileEntry.createWriter(function(fileWriter) {
                            fileWriter.onwriteend = function(e) {
                                console.log('Write completed.');
                                callback && callback("test.jpg");
                            };

                            fileWriter.onerror = function(e) {
                                console.log('Write failed: ' + e.toString());
                            };

                            fileWriter.write(bb.getBlob(contentType[extname]));
                        });
                    });
                };



    function convertDataURIToBinary(dataURI) {
    var BASE64_MARKER = ';base64,';
    var base64Index = dataURI.indexOf(BASE64_MARKER) + BASE64_MARKER.length;
    var base64 = dataURI.substring(base64Index);
    var raw = window.atob(base64);
    var rawLength = raw.length;
    var array = new Uint8Array(new ArrayBuffer(rawLength));

    for (i = 0; i < rawLength; i++) {
        array[i] = raw.charCodeAt(i);
    }
    return array;
}

ここから助けを得る jsfiddle

于 2012-08-10T08:48:32.573 に答える
1

XMLHttpRequest レベル 2 をサポートする最新のブラウザーでは、この回答に記載されている方法が機能するはずです。

関連する規格については、このブログ投稿で説明されています

于 2013-12-14T16:21:44.007 に答える
1

トリックは使用することですxhr.responseType = 'blob'

var fs = .... // your fileSystem
function download(fs,url,file,win,fail) {
  var xhr = new XMLHttpRequest();
  xhr.open('GET', url);
  xhr.responseType = "blob";
  xhr.onreadystatechange = function() {
    if (xhr.readyState == 4) {
      if(xhr.status === 200){
        fs.root.getFile(file,{create:true},function(fileEntry){
          fileEntry.createWriter(function(writer){
            writer.onwriteend = win;
            writer.onerror = fail;
            writer.write(xhr.response);
          })
        },fail)
      } else {
        fail(xhr.status);
      }
    }
  };
  xhr.send();
  return xhr;
};

cordova-promise-fsに基づく(開示: 私は著者です)

于 2014-11-29T16:55:58.997 に答える