1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277
|
// Copyright 2011 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @fileoverview Wrappers for the HTML5 File API. These wrappers closely mirror
* the underlying APIs, but use Closure-style events and Deferred return values.
* Their existence also makes it possible to mock the FileSystem API for testing
* in browsers that don't support it natively.
*
* When adding public functions to anything under this namespace, be sure to add
* its mock counterpart to goog.testing.fs.
*
*/
goog.provide('goog.fs');
goog.require('goog.array');
goog.require('goog.async.Deferred');
goog.require('goog.fs.Error');
goog.require('goog.fs.FileReader');
goog.require('goog.fs.FileSystemImpl');
goog.require('goog.fs.url');
goog.require('goog.userAgent');
/**
* Get a wrapped FileSystem object.
*
* @param {goog.fs.FileSystemType_} type The type of the filesystem to get.
* @param {number} size The size requested for the filesystem, in bytes.
* @return {!goog.async.Deferred} The deferred {@link goog.fs.FileSystem}. If an
* error occurs, the errback is called with a {@link goog.fs.Error}.
* @private
*/
goog.fs.get_ = function(type, size) {
var requestFileSystem =
goog.global.requestFileSystem || goog.global.webkitRequestFileSystem;
if (!goog.isFunction(requestFileSystem)) {
return goog.async.Deferred.fail(new Error('File API unsupported'));
}
var d = new goog.async.Deferred();
requestFileSystem(
type, size, function(fs) { d.callback(new goog.fs.FileSystemImpl(fs)); },
function(err) {
d.errback(new goog.fs.Error(err, 'requesting filesystem'));
});
return d;
};
/**
* The two types of filesystem.
*
* @enum {number}
* @private
*/
goog.fs.FileSystemType_ = {
/**
* A temporary filesystem may be deleted by the user agent at its discretion.
*/
TEMPORARY: 0,
/**
* A persistent filesystem will never be deleted without the user's or
* application's authorization.
*/
PERSISTENT: 1
};
/**
* Returns a temporary FileSystem object. A temporary filesystem may be deleted
* by the user agent at its discretion.
*
* @param {number} size The size requested for the filesystem, in bytes.
* @return {!goog.async.Deferred} The deferred {@link goog.fs.FileSystem}. If an
* error occurs, the errback is called with a {@link goog.fs.Error}.
*/
goog.fs.getTemporary = function(size) {
return goog.fs.get_(goog.fs.FileSystemType_.TEMPORARY, size);
};
/**
* Returns a persistent FileSystem object. A persistent filesystem will never be
* deleted without the user's or application's authorization.
*
* @param {number} size The size requested for the filesystem, in bytes.
* @return {!goog.async.Deferred} The deferred {@link goog.fs.FileSystem}. If an
* error occurs, the errback is called with a {@link goog.fs.Error}.
*/
goog.fs.getPersistent = function(size) {
return goog.fs.get_(goog.fs.FileSystemType_.PERSISTENT, size);
};
/**
* Creates a blob URL for a blob object.
* Throws an error if the browser does not support Object Urls.
*
* TODO(user): Update references to this method to use
* goog.fs.url.createObjectUrl instead.
*
* @param {!Blob} blob The object for which to create the URL.
* @return {string} The URL for the object.
*/
goog.fs.createObjectUrl = function(blob) {
return goog.fs.url.createObjectUrl(blob);
};
/**
* Revokes a URL created by {@link goog.fs.createObjectUrl}.
* Throws an error if the browser does not support Object Urls.
*
* TODO(user): Update references to this method to use
* goog.fs.url.revokeObjectUrl instead.
*
* @param {string} url The URL to revoke.
*/
goog.fs.revokeObjectUrl = function(url) {
goog.fs.url.revokeObjectUrl(url);
};
/**
* Checks whether this browser supports Object Urls. If not, calls to
* createObjectUrl and revokeObjectUrl will result in an error.
*
* TODO(user): Update references to this method to use
* goog.fs.url.browserSupportsObjectUrls instead.
*
* @return {boolean} True if this browser supports Object Urls.
*/
goog.fs.browserSupportsObjectUrls = function() {
return goog.fs.url.browserSupportsObjectUrls();
};
/**
* Concatenates one or more values together and converts them to a Blob.
*
* @param {...(string|!Blob|!ArrayBuffer)} var_args The values that will make up
* the resulting blob.
* @return {!Blob} The blob.
*/
goog.fs.getBlob = function(var_args) {
var BlobBuilder = goog.global.BlobBuilder || goog.global.WebKitBlobBuilder;
if (goog.isDef(BlobBuilder)) {
var bb = new BlobBuilder();
for (var i = 0; i < arguments.length; i++) {
bb.append(arguments[i]);
}
return bb.getBlob();
} else {
return goog.fs.getBlobWithProperties(goog.array.toArray(arguments));
}
};
/**
* Creates a blob with the given properties.
* See https://developer.mozilla.org/en-US/docs/Web/API/Blob for more details.
*
* @param {Array<string|!Blob>} parts The values that will make up the
* resulting blob.
* @param {string=} opt_type The MIME type of the Blob.
* @param {string=} opt_endings Specifies how strings containing newlines are to
* be written out.
* @return {!Blob} The blob.
*/
goog.fs.getBlobWithProperties = function(parts, opt_type, opt_endings) {
var BlobBuilder = goog.global.BlobBuilder || goog.global.WebKitBlobBuilder;
if (goog.isDef(BlobBuilder)) {
var bb = new BlobBuilder();
for (var i = 0; i < parts.length; i++) {
bb.append(parts[i], opt_endings);
}
return bb.getBlob(opt_type);
} else if (goog.isDef(goog.global.Blob)) {
var properties = {};
if (opt_type) {
properties['type'] = opt_type;
}
if (opt_endings) {
properties['endings'] = opt_endings;
}
return new Blob(parts, properties);
} else {
throw new Error('This browser doesn\'t seem to support creating Blobs');
}
};
/**
* Converts a Blob or a File into a string. This should only be used when the
* blob is known to be small.
*
* @param {!Blob} blob The blob to convert.
* @param {string=} opt_encoding The name of the encoding to use.
* @return {!goog.async.Deferred} The deferred string. If an error occurrs, the
* errback is called with a {@link goog.fs.Error}.
* @deprecated Use {@link goog.fs.FileReader.readAsText} instead.
*/
goog.fs.blobToString = function(blob, opt_encoding) {
return goog.fs.FileReader.readAsText(blob, opt_encoding);
};
/**
* Slices the blob. The returned blob contains data from the start byte
* (inclusive) till the end byte (exclusive). Negative indices can be used
* to count bytes from the end of the blob (-1 == blob.size - 1). Indices
* are always clamped to blob range. If end is omitted, all the data till
* the end of the blob is taken.
*
* @param {!Blob} blob The blob to be sliced.
* @param {number} start Index of the starting byte.
* @param {number=} opt_end Index of the ending byte.
* @return {Blob} The blob slice or null if not supported.
*/
goog.fs.sliceBlob = function(blob, start, opt_end) {
if (!goog.isDef(opt_end)) {
opt_end = blob.size;
}
if (blob.webkitSlice) {
// Natively accepts negative indices, clamping to the blob range and
// range end is optional. See http://trac.webkit.org/changeset/83873
return blob.webkitSlice(start, opt_end);
} else if (blob.mozSlice) {
// Natively accepts negative indices, clamping to the blob range and
// range end is optional. See https://developer.mozilla.org/en/DOM/Blob
// and http://hg.mozilla.org/mozilla-central/rev/dae833f4d934
return blob.mozSlice(start, opt_end);
} else if (blob.slice) {
// Old versions of Firefox and Chrome use the original specification.
// Negative indices are not accepted, only range end is clamped and
// range end specification is obligatory.
// See http://www.w3.org/TR/2009/WD-FileAPI-20091117/
if ((goog.userAgent.GECKO && !goog.userAgent.isVersionOrHigher('13.0')) ||
(goog.userAgent.WEBKIT && !goog.userAgent.isVersionOrHigher('537.1'))) {
if (start < 0) {
start += blob.size;
}
if (start < 0) {
start = 0;
}
if (opt_end < 0) {
opt_end += blob.size;
}
if (opt_end < start) {
opt_end = start;
}
return blob.slice(start, opt_end - start);
}
// IE and the latest versions of Firefox and Chrome use the new
// specification. Natively accepts negative indices, clamping to the blob
// range and range end is optional.
// See http://dev.w3.org/2006/webapi/FileAPI/
return blob.slice(start, opt_end);
}
return null;
};
|