Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: browser support blob #409

Merged
merged 9 commits into from
Mar 29, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 22 additions & 4 deletions example/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ <h1>OSS <small>in</small> Browser</h1>
<div class="form-group">
<label>Store as</label>
<input type="text" class="form-control" id="object-key-content" value="object" />
</div>
<div class="form-group">
<input type="button" class="btn btn-primary" id="content-button" value="Save" />
</div>
Expand All @@ -72,6 +71,26 @@ <h1>OSS <small>in</small> Browser</h1>
</td>
</tr>
<tr>
<td>
<div class="panel panel-success">
<div class="panel-heading">Upload Blob</div>
<div class="panel-body">
<form action="" class="form-horizontal">
<div class="form-group">
<label>Content</label>
<textarea class="form-control" id="file-blob" rows="3">Hello, OSS! I am a Blob!</textarea>
</div>
<div class="form-group">
<label>Store as</label>
<input type="text" class="form-control" id="object-key-blob" value="blob" />
</div>
<div class="form-group">
<input type="button" class="btn btn-primary" id="blob-button" value="Save" />
</div>
</form>
</div>
</div>
</td>
<td>
<div class="panel panel-danger">
<div class="panel-heading">Upload with base64 img</div>
Expand Down Expand Up @@ -104,7 +123,8 @@ <h1>OSS <small>in</small> Browser</h1>
</div>
</div>
</td>

</tr>
<tr>
<td>
<div class="panel panel-warning">
<div class="panel-heading">Download file</div>
Expand All @@ -125,8 +145,6 @@ <h1>OSS <small>in</small> Browser</h1>
</div>
</div>
</td>
</tr>
<tr>
<td>
<div class="panel panel-info">
<div class="panel-heading">List files</div>
Expand Down
12 changes: 12 additions & 0 deletions example/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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);
};
Expand Down
21 changes: 17 additions & 4 deletions lib/browser/managed_upload.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -176,13 +185,17 @@ is.file = function (file) {
return typeof (File) !== 'undefined' && file 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);
Expand Down Expand Up @@ -255,7 +268,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)) {
Expand Down
17 changes: 11 additions & 6 deletions lib/browser/object.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,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 || {};
Expand Down
55 changes: 55 additions & 0 deletions test/browser/browser.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});
Expand Down Expand Up @@ -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');
Expand Down
Binary file removed test/node/.tmp/content-type-by-file
Binary file not shown.
Binary file removed test/node/.tmp/content-type-by-file.jpg
Binary file not shown.
Loading