123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747 |
- goog.provide('goog.net.FileDownloader');
- goog.provide('goog.net.FileDownloader.Error');
- goog.require('goog.Disposable');
- goog.require('goog.asserts');
- goog.require('goog.async.Deferred');
- goog.require('goog.crypt.hash32');
- goog.require('goog.debug.Error');
- goog.require('goog.events');
- goog.require('goog.events.EventHandler');
- goog.require('goog.fs');
- goog.require('goog.fs.DirectoryEntry');
- goog.require('goog.fs.Error');
- goog.require('goog.fs.FileSaver');
- goog.require('goog.net.EventType');
- goog.require('goog.net.XhrIo');
- goog.require('goog.net.XhrIoPool');
- goog.require('goog.object');
- goog.net.FileDownloader = function(dir, opt_pool) {
- goog.net.FileDownloader.base(this, 'constructor');
-
- this.dir_ = dir;
-
- this.pool_ = opt_pool || new goog.net.XhrIoPool();
-
- this.downloads_ = {};
-
- this.eventHandler_ = new goog.events.EventHandler(this);
- };
- goog.inherits(goog.net.FileDownloader, goog.Disposable);
- goog.net.FileDownloader.prototype.download = function(url) {
- if (this.isDownloading(url)) {
- return this.downloads_[url].deferred.branch(true );
- }
- var download = new goog.net.FileDownloader.Download_(url, this);
- this.downloads_[url] = download;
- this.pool_.getObject(goog.bind(this.gotXhr_, this, download));
- return download.deferred.branch(true );
- };
- goog.net.FileDownloader.prototype.waitForDownload = function(url) {
- var deferred = new goog.async.Deferred();
- if (this.isDownloading(url)) {
- this.downloads_[url].deferred.addBoth(function() {
- deferred.callback(null);
- }, this);
- } else {
- deferred.callback(null);
- }
- return deferred;
- };
- goog.net.FileDownloader.prototype.isDownloading = function(url) {
- return url in this.downloads_;
- };
- goog.net.FileDownloader.prototype.getDownloadedBlob = function(url) {
- return this.getFile_(url).addCallback(function(fileEntry) {
- return fileEntry.file();
- });
- };
- goog.net.FileDownloader.prototype.getLocalUrl = function(url) {
- return this.getFile_(url).addCallback(function(fileEntry) {
- return fileEntry.toUrl();
- });
- };
- goog.net.FileDownloader.prototype.isDownloaded = function(url) {
- var deferred = new goog.async.Deferred();
- var blobDeferred = this.getDownloadedBlob(url);
- blobDeferred.addCallback(function() { deferred.callback(true); });
- blobDeferred.addErrback(function(err) {
- if (err.name == goog.fs.Error.ErrorName.NOT_FOUND) {
- deferred.callback(false);
- } else {
- deferred.errback(err);
- }
- });
- return deferred;
- };
- goog.net.FileDownloader.prototype.remove = function(url) {
- return this.getDir_(url, goog.fs.DirectoryEntry.Behavior.DEFAULT)
- .addCallback(function(dir) { return dir.removeRecursively(); });
- };
- goog.net.FileDownloader.prototype.setBlob = function(url, blob, opt_name) {
- var name = this.sanitize_(opt_name || this.urlToName_(url));
- var download = new goog.net.FileDownloader.Download_(url, this);
- this.downloads_[url] = download;
- download.blob = blob;
- this.getDir_(download.url, goog.fs.DirectoryEntry.Behavior.CREATE_EXCLUSIVE)
- .addCallback(function(dir) {
- return dir.getFile(
- name, goog.fs.DirectoryEntry.Behavior.CREATE_EXCLUSIVE);
- })
- .addCallback(goog.bind(this.fileSuccess_, this, download))
- .addErrback(goog.bind(this.error_, this, download));
- return download.deferred.branch(true );
- };
- goog.net.FileDownloader.prototype.gotXhr_ = function(download, xhr) {
- if (download.cancelled) {
- this.freeXhr_(xhr);
- return;
- }
- this.eventHandler_.listen(
- xhr, goog.net.EventType.SUCCESS,
- goog.bind(this.xhrSuccess_, this, download));
- this.eventHandler_.listen(
- xhr, [goog.net.EventType.ERROR, goog.net.EventType.ABORT],
- goog.bind(this.error_, this, download));
- this.eventHandler_.listen(
- xhr, goog.net.EventType.READY, goog.bind(this.freeXhr_, this, xhr));
- download.xhr = xhr;
- xhr.setResponseType(goog.net.XhrIo.ResponseType.ARRAY_BUFFER);
- xhr.send(download.url);
- };
- goog.net.FileDownloader.prototype.xhrSuccess_ = function(download) {
- if (download.cancelled) {
- return;
- }
- var name = this.sanitize_(
- this.getName_(
- (download.xhr)));
- var resp = (download.xhr.getResponse());
- if (!resp) {
-
-
-
-
- this.error_(download);
- return;
- }
- download.blob = goog.fs.getBlob(resp);
- delete download.xhr;
- this.getDir_(download.url, goog.fs.DirectoryEntry.Behavior.CREATE_EXCLUSIVE)
- .addCallback(function(dir) {
- return dir.getFile(
- name, goog.fs.DirectoryEntry.Behavior.CREATE_EXCLUSIVE);
- })
- .addCallback(goog.bind(this.fileSuccess_, this, download))
- .addErrback(goog.bind(this.error_, this, download));
- };
- goog.net.FileDownloader.prototype.fileSuccess_ = function(download, file) {
- if (download.cancelled) {
- file.remove();
- return;
- }
- download.file = file;
- file.createWriter()
- .addCallback(goog.bind(this.fileWriterSuccess_, this, download))
- .addErrback(goog.bind(this.error_, this, download));
- };
- goog.net.FileDownloader.prototype.fileWriterSuccess_ = function(
- download, writer) {
- if (download.cancelled) {
- download.file.remove();
- return;
- }
- download.writer = writer;
- writer.write( (download.blob));
- this.eventHandler_.listenOnce(
- writer, goog.fs.FileSaver.EventType.WRITE_END,
- goog.bind(this.writeEnd_, this, download));
- };
- goog.net.FileDownloader.prototype.writeEnd_ = function(download) {
- if (download.cancelled || download.writer.getError()) {
- this.error_(download, download.writer.getError());
- return;
- }
- delete this.downloads_[download.url];
- download.deferred.callback(download.blob);
- };
- goog.net.FileDownloader.prototype.error_ = function(download, opt_err) {
- if (download.file) {
- download.file.remove();
- }
- if (download.cancelled) {
- return;
- }
- delete this.downloads_[download.url];
- download.deferred.errback(
- new goog.net.FileDownloader.Error(download, opt_err));
- };
- goog.net.FileDownloader.prototype.cancel_ = function(download) {
- goog.dispose(download);
- delete this.downloads_[download.url];
- };
- goog.net.FileDownloader.prototype.getDir_ = function(url, behavior) {
-
-
-
-
-
-
-
-
-
-
- var dirname = '`' +
- Math.abs(goog.crypt.hash32.encodeString(url))
- .toString(16)
- .substring(0, 3);
- return this.dir_.getDirectory(dirname, goog.fs.DirectoryEntry.Behavior.CREATE)
- .addCallback(function(dir) {
- return dir.getDirectory(this.sanitize_(url), behavior);
- }, this);
- };
- goog.net.FileDownloader.prototype.getFile_ = function(url) {
- return this.getDir_(url, goog.fs.DirectoryEntry.Behavior.DEFAULT)
- .addCallback(function(dir) {
- return dir.listDirectory().addCallback(function(files) {
- goog.asserts.assert(files.length == 1);
-
-
-
- return files[0] || dir.getFile('file');
- });
- });
- };
- goog.net.FileDownloader.prototype.sanitize_ = function(str) {
-
-
-
-
-
- return '`' +
- str.replace(/[\/\\<>:?*"|%`]/g, encodeURIComponent).replace(/%/g, '`');
- };
- goog.net.FileDownloader.prototype.getName_ = function(xhr) {
- var disposition = xhr.getResponseHeader('Content-Disposition');
- var match =
- disposition && disposition.match(/^attachment *; *filename="(.*)"$/i);
- if (match) {
-
-
-
- return match[1].replace(/\\(.)/g, '$1');
- }
- return this.urlToName_(xhr.getLastUri());
- };
- goog.net.FileDownloader.prototype.urlToName_ = function(url) {
- var segments = url.split('/');
- return segments[segments.length - 1];
- };
- goog.net.FileDownloader.prototype.freeXhr_ = function(xhr) {
- goog.events.removeAll(xhr);
- this.pool_.addFreeObject(xhr);
- };
- goog.net.FileDownloader.prototype.disposeInternal = function() {
- delete this.dir_;
- goog.dispose(this.eventHandler_);
- delete this.eventHandler_;
- goog.object.forEach(this.downloads_, function(download) {
- download.deferred.cancel();
- }, this);
- delete this.downloads_;
- goog.dispose(this.pool_);
- delete this.pool_;
- goog.net.FileDownloader.base(this, 'disposeInternal');
- };
- goog.net.FileDownloader.Error = function(download, opt_fsErr) {
- goog.net.FileDownloader.Error.base(
- this, 'constructor', 'Error capturing URL ' + download.url);
-
- this.url = download.url;
- if (download.xhr) {
- this.xhrStatus = download.xhr.getStatus();
- this.xhrErrorCode = download.xhr.getLastErrorCode();
- this.message += ': XHR failed with status ' + this.xhrStatus +
- ' (error code ' + this.xhrErrorCode + ')';
- } else if (opt_fsErr) {
- this.fileError = opt_fsErr;
- this.message += ': file API failed (' + opt_fsErr.message + ')';
- }
- };
- goog.inherits(goog.net.FileDownloader.Error, goog.debug.Error);
- goog.net.FileDownloader.Error.prototype.xhrStatus;
- goog.net.FileDownloader.Error.prototype.xhrErrorCode;
- goog.net.FileDownloader.Error.prototype.fileError;
- goog.net.FileDownloader.Download_ = function(url, downloader) {
- goog.net.FileDownloader.Download_.base(this, 'constructor');
-
- this.url = url;
-
- this.deferred =
- new goog.async.Deferred(goog.bind(downloader.cancel_, downloader, this));
-
- this.cancelled = false;
-
- this.xhr = null;
-
- this.name = null;
-
- this.blob = null;
-
- this.file = null;
-
- this.writer = null;
- };
- goog.inherits(goog.net.FileDownloader.Download_, goog.Disposable);
- goog.net.FileDownloader.Download_.prototype.disposeInternal = function() {
- this.cancelled = true;
- if (this.xhr) {
- this.xhr.abort();
- } else if (
- this.writer &&
- this.writer.getReadyState() == goog.fs.FileSaver.ReadyState.WRITING) {
- this.writer.abort();
- }
- goog.net.FileDownloader.Download_.base(this, 'disposeInternal');
- };
|