diff --git a/example/index.html b/example/index.html index 2f3e5a443..f3403a3f8 100644 --- a/example/index.html +++ b/example/index.html @@ -62,7 +62,6 @@

OSS in Browser

-
@@ -72,6 +71,26 @@

OSS in Browser

+ +
+
Upload Blob
+
+
+
+ + +
+
+ + +
+
+ +
+
+
+
+
Upload with base64 img
@@ -104,7 +123,8 @@

OSS in Browser

- + +
Download file
@@ -125,8 +145,6 @@

OSS in Browser

- -
List files
diff --git a/example/index.js b/example/index.js index 67fc4803f..2633e8b64 100644 --- a/example/index.js +++ b/example/index.js @@ -174,6 +174,14 @@ const uploadContent = function (client) { return client.put(key, new Buffer(content)).then(res => listFiles(client)); }; +const uploadBlob = function (client) { + const content = document.getElementById('file-blob').value.trim(); + const key = document.getElementById('object-key-blob').value.trim() || 'blob'; + console.log(`content => ${key}`); + + return client.put(key, new Blob([content], { type: 'text/plain' })).then(res => listFiles(client)); +} + const downloadFile = function (client) { const object = document.getElementById('dl-object-key').value.trim(); @@ -209,6 +217,10 @@ window.onload = function () { applyTokenDo(uploadContent); }; + document.getElementById('blob-button').onclick = function () { + applyTokenDo(uploadBlob); + }; + document.getElementById('list-files-button').onclick = function () { applyTokenDo(listFiles); }; diff --git a/lib/browser/managed_upload.js b/lib/browser/managed_upload.js index 5c0f6fbb6..f7c47f0bb 100644 --- a/lib/browser/managed_upload.js +++ b/lib/browser/managed_upload.js @@ -36,8 +36,17 @@ proto.multipartUpload = function* multipartUpload(name, file, options) { } const minPartSize = 100 * 1024; - const filename = is.file(file) ? file.name : file; - options.mime = options.mime || mime.getType(path.extname(filename)); + + if (!options.mime) { + if (is.file(file)) { + options.mime = mime.getType(path.extname(file.name)); + } else if (is.blob(file)) { + options.mime = file.type; + } else { + options.mime = mime.getType(path.extname(file)); + } + } + options.headers = options.headers || {}; this._convertMetaToHeaders(options.meta, options.headers); @@ -182,13 +191,17 @@ is.file = function file(obj) { return typeof (File) !== 'undefined' && obj instanceof File; }; +is.blob = function (blob) { + return typeof (Blob) !== 'undefined' && blob instanceof Blob; +}; + /** * Get file size */ proto._getFileSize = function* _getFileSize(file) { if (is.buffer(file)) { return file.length; - } else if (is.file(file)) { + } else if (is.blob(file) || is.file(file)) { return file.size; } if (is.string(file)) { const stat = yield this._statFile(file); @@ -261,7 +274,7 @@ WebFileReadStream.prototype._read = function _read(size) { }; proto._createStream = function _createStream(file, start, end) { - if (is.file(file)) { + if (is.blob(file) || is.file(file)) { return new WebFileReadStream(file.slice(start, end)); } // else if (is.string(file)) { diff --git a/lib/browser/object.js b/lib/browser/object.js index 6ceed25ac..23fd543d0 100644 --- a/lib/browser/object.js +++ b/lib/browser/object.js @@ -65,15 +65,20 @@ proto.put = function* put(name, file, options) { options = options || {}; if (is.buffer(file)) { content = file; - } else if (is.string(file)) { - options.mime = options.mime || mime.getType(path.extname(file)); - const stream = fs.createReadStream(file); + } else if (is.blob(file) || is.file(file)) { + if (!options.mime) { + if (is.file(file)) { + options.mime = mime.getType(path.extname(file.name)); + } else { + options.mime = file.type; + } + } + + const stream = this._createStream(file, 0, file.size); options.contentLength = yield this._getFileSize(file); return yield this.putStream(name, stream, options); - } else if (is.readableStream(file)) { - return yield this.putStream(name, file, options); } else { - throw new TypeError('Must provide String/Buffer/ReadableStream for put.'); + throw new TypeError('Must provide Buffer/Blob for put.'); } options.headers = options.headers || {}; diff --git a/test/browser/browser.test.js b/test/browser/browser.test.js index e169bc184..48d0747aa 100644 --- a/test/browser/browser.test.js +++ b/test/browser/browser.test.js @@ -471,6 +471,28 @@ describe('browser', () => { assert.equal(resultGet.content.toString(), body.toString()); + const resultDel = yield this.store.delete(name); + assert.equal(resultDel.res.status, 204); + }); + it('GETs and PUTs blob to a bucket', function* () { + const name = `${prefix}put/test`; + const body = new Blob(['blobBody'], { type: 'text/plain' }); + const resultPut = yield this.store.put(name, body); + assert.equal(resultPut.res.status, 200); + const resultGet = yield this.store.get(name); + assert.equal(resultGet.res.status, 200); + + + yield new Promise((resolve) => { + const fr = new FileReader(); + fr.onload = function () { + console.log(fr.result); + assert.equal(resultGet.content.toString(), fr.result); + resolve(); + }; + fr.readAsText(body, 'utf-8'); + }); + const resultDel = yield this.store.delete(name); assert.equal(resultDel.res.status, 204); }); @@ -762,6 +784,39 @@ describe('browser', () => { assert.deepEqual(md5(object.content), md5(fileBuf)); }); + it('should upload file using multipart upload', function* () { + // create a file with 1M random data + const blobContent = Array(1024 * 1024).fill('a').join(''); + const blob = new Blob([blobContent], { type: 'text/plain' }); + + const name = `${prefix}multipart/upload-blob.js`; + let progress = 0; + const result = yield this.store.multipartUpload(name, blob, { + partSize: 100 * 1024, + progress() { + return function (done) { + progress++; + done(); + }; + }, + }); + sinon.restore(); + assert.equal(result.res.status, 200); + assert.equal(progress, 12); + + const object = yield this.store.get(name); + assert.equal(object.res.status, 200); + + const blobBuf = new Uint8Array(blobContent.length); + for (let i = 0, j = blobContent.length; i < j; ++i) { + blobBuf[i] = blobContent.charCodeAt(i); + } + + assert.equal(object.content.length, blobBuf.length); + // avoid comparing buffers directly for it may hang when generating diffs + assert.deepEqual(md5(object.content), md5(blobBuf)); + }); + it('should return requestId in init, upload part, complete', function* () { const fileContent = Array(1024 * 1024).fill('a').join(''); const file = new File([fileContent], 'multipart-fallback');