From fe9a0c969d228bb71928aa422a99d607a4b99977 Mon Sep 17 00:00:00 2001 From: Wenbo Yu Date: Tue, 9 Jan 2018 18:05:47 -0800 Subject: [PATCH] Update: support uploading new version (#146) --- src/api/PlainUpload.js | 35 +++++++++------ src/api/__tests__/PlainUpload-test.js | 43 +++++-------------- src/api/uploads/MultiputUpload.js | 19 +++++--- .../ContentUploader/ContentUploader.js | 24 +++++++---- 4 files changed, 58 insertions(+), 63 deletions(-) diff --git a/src/api/PlainUpload.js b/src/api/PlainUpload.js index ee299664b3..0be0a736ed 100644 --- a/src/api/PlainUpload.js +++ b/src/api/PlainUpload.js @@ -10,7 +10,8 @@ import type { BoxItem } from '../flowTypes'; class PlainUpload extends BaseUpload { file: File; - id: string; + folderId: string; + fileId: ?string; overwrite: boolean; retryTimeout: number; successCallback: Function; @@ -94,6 +95,10 @@ class PlainUpload extends BaseUpload { return; } + if (!this.fileId && !!fileId) { + this.fileId = fileId; + } + let url = `${this.getBaseUrl()}/files/content`; if (fileId) { url = url.replace('content', `${fileId}/content`); @@ -102,7 +107,7 @@ class PlainUpload extends BaseUpload { const { size, name } = this.file; const attributes = { name: fileName || name, - parent: { id: this.id }, + parent: { id: this.folderId }, size }; @@ -120,11 +125,9 @@ class PlainUpload extends BaseUpload { * * @param {Object} - Request options * @param {boolean} [options.url] - Upload URL to use - * @param {string} [options.fileId] - ID of file to replace - * @param {string} [options.fileName] - New name for file * @return {Promise<*>} */ - async makeRequest({ url, fileId, fileName }: { url?: string, fileId?: string, fileName?: string }): Promise<*> { + async makeRequest({ url }: { url?: string }): Promise<*> { if (this.isDestroyed()) { return; } @@ -136,14 +139,14 @@ class PlainUpload extends BaseUpload { if (!uploadUrl) { uploadUrl = `${this.uploadHost}/api/2.0/files/content`; - if (fileId) { - uploadUrl = uploadUrl.replace('content', `${fileId}/content`); + if (this.fileId) { + uploadUrl = uploadUrl.replace('content', `${this.fileId}/content`); } } const attributes = JSON.stringify({ - name: fileName || this.file.name, - parent: { id: this.id } + name: this.file.name, + parent: { id: this.folderId } }); this.xhr.uploadFile({ @@ -163,7 +166,8 @@ class PlainUpload extends BaseUpload { * Otherwise, re-upload with a different name. * * @param {Object} options - Upload options - * @param {string} options.id - Folder id + * @param {string} options.folderId - untyped folder id + * @param {string} [options.fileId] - Untyped file id (e.g. no "file_" prefix) * @param {File} options.file - File blob object * @param {Function} [options.successCallback] - Function to call with response * @param {Function} [options.errorCallback] - Function to call with errors @@ -172,14 +176,16 @@ class PlainUpload extends BaseUpload { * @return {void} */ upload({ - id, + folderId, + fileId, file, successCallback = noop, errorCallback = noop, progressCallback = noop, overwrite = true }: { - id: string, + folderId: string, + fileId: ?string, file: File, successCallback: Function, errorCallback: Function, @@ -191,14 +197,15 @@ class PlainUpload extends BaseUpload { } // Save references - this.id = id; + this.folderId = folderId; + this.fileId = fileId; this.file = file; this.successCallback = successCallback; this.errorCallback = errorCallback; this.progressCallback = progressCallback; this.overwrite = overwrite; - this.makePreflightRequest({}); + this.makePreflightRequest(fileId ? { fileId } : {}); } /** diff --git a/src/api/__tests__/PlainUpload-test.js b/src/api/__tests__/PlainUpload-test.js index be107dbf28..2d239efc90 100644 --- a/src/api/__tests__/PlainUpload-test.js +++ b/src/api/__tests__/PlainUpload-test.js @@ -126,7 +126,7 @@ describe('api/PlainUpload', () => { size: 1, name: 'zavala' }; - upload.id = '123'; + upload.folderId = '123'; upload.xhr = { options: jest.fn() @@ -138,7 +138,7 @@ describe('api/PlainUpload', () => { data: { name: upload.file.name, parent: { - id: upload.id + id: upload.folderId }, size: upload.file.size }, @@ -157,7 +157,7 @@ describe('api/PlainUpload', () => { size: 1, name: 'zavala' }; - upload.id = '123'; + upload.folderId = '123'; upload.xhr = { options: jest.fn() @@ -194,7 +194,7 @@ describe('api/PlainUpload', () => { upload.file = { name: 'warlock' }; - upload.id = '123'; + upload.folderId = '123'; upload.xhr = { uploadFile: jest.fn() }; @@ -219,14 +219,13 @@ describe('api/PlainUpload', () => { upload.file = { name: 'warlock' }; - upload.id = '123'; + upload.fileId = fileId; + upload.folderId = '123'; upload.xhr = { uploadFile: jest.fn() }; - await upload.makeRequest({ - fileId - }); + await upload.makeRequest({}); expect(upload.xhr.uploadFile).toHaveBeenCalledWith({ url: `${upload.uploadHost}/api/2.0/files/${fileId}/content`, data: expect.any(Object), @@ -235,28 +234,6 @@ describe('api/PlainUpload', () => { progressHandler: expect.any(Function) }); }); - - test('should stringify name and parent for upload data', async () => { - const name = 'titan'; - const parentId = '123'; - JSON.stringify = jest.fn(); - - upload.isDestroyed = jest.fn().mockReturnValueOnce(false); - upload.id = parentId; - upload.xhr = { - uploadFile: jest.fn() - }; - - await upload.makeRequest({ - fileName: name - }); - expect(JSON.stringify).toHaveBeenCalledWith({ - name, - parent: { - id: parentId - } - }); - }); }); describe('upload()', () => { @@ -268,7 +245,7 @@ describe('api/PlainUpload', () => { }); test('should set properties and make preflight request', () => { - const id = '123'; + const folderId = '123'; const file = {}; const successCallback = () => {}; const errorCallback = () => {}; @@ -278,7 +255,7 @@ describe('api/PlainUpload', () => { upload.isDestroyed = jest.fn().mockReturnValueOnce(false); upload.makePreflightRequest = jest.fn(); upload.upload({ - id, + folderId, file, successCallback, errorCallback, @@ -286,7 +263,7 @@ describe('api/PlainUpload', () => { overwrite }); - expect(upload.id).toBe(id); + expect(upload.folderId).toBe(folderId); expect(upload.file).toBe(file); expect(upload.successCallback).toBe(successCallback); expect(upload.errorCallback).toBe(errorCallback); diff --git a/src/api/uploads/MultiputUpload.js b/src/api/uploads/MultiputUpload.js index 2bb645149d..46701b48ea 100644 --- a/src/api/uploads/MultiputUpload.js +++ b/src/api/uploads/MultiputUpload.js @@ -33,7 +33,7 @@ class MultiputUpload extends BaseMultiput { commitRetryCount: number; createSessionNumRetriesPerformed: number; destinationFileId: ?string; - folderId: ?string; + folderId: string; file: File; fileSha1: ?string; firstUnuploadedPartIndex: number; @@ -101,7 +101,8 @@ class MultiputUpload extends BaseMultiput { * * @param {Object} options * @param {File} options.file - * @param {string} [options.id] - Untyped folder id (e.g. no "d_" prefix) + * @param {string} options.folderId - Untyped folder id (e.g. no "folder_" prefix) + * @param {string} [options.fileId] - Untyped file id (e.g. no "file_" prefix) * @param {Function} [options.errorCallback] * @param {Function} [options.progressCallback] * @param {Function} [options.successCallback] @@ -109,7 +110,7 @@ class MultiputUpload extends BaseMultiput { */ upload = ({ file, - id, + folderId, errorCallback, progressCallback, successCallback, @@ -117,12 +118,12 @@ class MultiputUpload extends BaseMultiput { fileId }: { file: File, - id?: ?string, + folderId: string, errorCallback?: Function, progressCallback?: Function, successCallback?: Function, overwrite?: boolean, - fileId?: string + fileId: ?string }): void => { this.file = file; this.fileName = this.file.name; @@ -130,7 +131,7 @@ class MultiputUpload extends BaseMultiput { // a file change during the upload. this.initialFileSize = this.file.size; this.initialFileLastModified = getFileLastModifiedAsISONoMSIfPossible(this.file); - this.folderId = id; + this.folderId = folderId; this.errorCallback = errorCallback || noop; this.progressCallback = progressCallback || noop; this.successCallback = successCallback || noop; @@ -472,7 +473,11 @@ class MultiputUpload extends BaseMultiput { }: { buffer: ArrayBuffer, readCompleteTimestamp: number } = await this.readFile(reader, blob); const sha256ArrayBuffer = await digest('SHA-256', buffer); const sha256 = btoa( - new Uint8Array(sha256ArrayBuffer).reduce((data, byte) => data + String.fromCharCode(byte), '') + Array.prototype.reduce.call( + new Uint8Array(sha256ArrayBuffer), + (data, byte) => data + String.fromCharCode(byte), + '' + ) ); this.sendPartToWorker(part, buffer); diff --git a/src/components/ContentUploader/ContentUploader.js b/src/components/ContentUploader/ContentUploader.js index ba8e7fae49..e95c10af49 100644 --- a/src/components/ContentUploader/ContentUploader.js +++ b/src/components/ContentUploader/ContentUploader.js @@ -29,7 +29,9 @@ import { STATUS_IN_PROGRESS, STATUS_COMPLETE, STATUS_ERROR, - ERROR_CODE_UPLOAD_FILE_LIMIT + ERROR_CODE_UPLOAD_FILE_LIMIT, + TYPED_ID_FOLDER_PREFIX, + TYPED_ID_FILE_PREFIX } from '../../constants'; import type { BoxItem, @@ -181,8 +183,11 @@ class ContentUploader extends Component { const itemFolderId = uploadAPIOptions && uploadAPIOptions.folderId - ? `folder_${uploadAPIOptions.folderId}` - : `folder_${rootFolderId}`; + ? `${TYPED_ID_FOLDER_PREFIX}${uploadAPIOptions.folderId}` + : `${TYPED_ID_FOLDER_PREFIX}${rootFolderId}`; + const itemFileId = + uploadAPIOptions && uploadAPIOptions.fileId ? `${TYPED_ID_FILE_PREFIX}${uploadAPIOptions.fileId}` : null; + const options = { token, sharedLink, @@ -191,7 +196,7 @@ class ContentUploader extends Component { uploadHost, clientName, responseFilter, - id: itemFolderId, + id: itemFileId || itemFolderId, ...uploadAPIOptions }; return new API(options); @@ -405,16 +410,17 @@ class ContentUploader extends Component { this.numItemsUploading += 1; - api.upload({ - // TODO: rename id to folderId + const uploadOptions: Object = { file, - id: options && options.folderId ? options.folderId : rootFolderId, + folderId: options && options.folderId ? options.folderId : rootFolderId, errorCallback: (error) => this.handleUploadError(item, error), progressCallback: (event) => this.handleUploadProgress(item, event), successCallback: (entries) => this.handleUploadSuccess(item, entries), overwrite: true, - fileId: options && options.fileId ? options.fileId : undefined - }); + fileId: options && options.fileId ? options.fileId : null + }; + + api.upload(uploadOptions); item.status = STATUS_IN_PROGRESS; const { items } = this.state;