New: Chunked uploads#15
Conversation
priyajeet
left a comment
There was a problem hiding this comment.
Still 1 file left to review, the big one
|
|
||
| class Chunk extends Base { | ||
| cancelled: boolean; | ||
| chunk: Object | null; |
There was a problem hiding this comment.
I think you can do ?Object, then | null can be removed
| data: Object = {}; | ||
| progress: number = 0; | ||
| retry: number; | ||
| uploadHeaders: Object; |
There was a problem hiding this comment.
type StringMap from flowTypes
| * @returns {void} | ||
| */ | ||
| upload(): void { | ||
| if (this.cancelled) { |
There was a problem hiding this comment.
If subclassing Base.js, it has the concept of this.isDestroyed(), can reuse that. See other API files.
| clearTimeout(this.retry); | ||
| this.chunk = null; | ||
| this.data = {}; | ||
| this.cancelled = true; |
There was a problem hiding this comment.
this.destroy() can be used here
|
|
||
| const UPLOAD_RETRY_INTERVAL_MS = 1000; | ||
|
|
||
| class Chunk extends Base { |
There was a problem hiding this comment.
Any reason this needs to be a child of Base?
There was a problem hiding this comment.
Auth information + needs its own XHR.
| * @return {string} | ||
| */ | ||
| /* eslint-disable no-bitwise */ | ||
| export default function(numArray: Int32Array): string { |
There was a problem hiding this comment.
Probably add a test for this file while you are at it, you can steal it from jsperf
| delete hdrs.Accept; | ||
| delete hdrs['Content-Type']; | ||
|
|
||
| if (headers['Content-Type']) { |
There was a problem hiding this comment.
Content-Type string being repeated 4+ times
| Object.keys(data).forEach((key) => { | ||
| formData.append(key, data[key]); | ||
| }); | ||
| postFile({ |
There was a problem hiding this comment.
Probably can rename to upload or something, since its PUT/POST both
| this.destroy(); | ||
| this.uploadAPI = new UploadAPI(this.options); | ||
| getUploadAPI(chunked?: boolean, fileSize?: number): ChunkedUploadAPI | PlainUploadAPI { | ||
| if (this.uploadAPI) { |
There was a problem hiding this comment.
Any reason why you are returning the prior one?
What if it was destroyed()?
There was a problem hiding this comment.
I need to be able to cancel - fetching a different API won't cancel the right one.
| this.chunks = []; | ||
|
|
||
| // Abort upload session | ||
| this.xhr.delete(`${this.uploadHost}/api/2.0/files/upload_sessions/${this.sessionId}`); |
There was a problem hiding this comment.
Maybe have this as a function somewhere, I think there is another place its used
| * @returns {void} | ||
| */ | ||
| cancel(): void { | ||
| // Cancel individual upload chunks |
There was a problem hiding this comment.
Probably add destroyedCheck()
| * @return {Promise} | ||
| */ | ||
| getNextChunk(): Promise<any> { | ||
| return new Promise((resolve, reject) => { |
There was a problem hiding this comment.
Should add destroyedCheck
| } else { | ||
| // Otherwise, reupload and append timestamp | ||
| // 'test.jpg' becomes 'test-TIMESTAMP.jpg' | ||
| const extension = name.substr(name.lastIndexOf('.')) || ''; |
There was a problem hiding this comment.
bug when file has no extension
There was a problem hiding this comment.
you can also pass in the name from the file object
also see RenameDialog.js
There was a problem hiding this comment.
Known issue - there's no good cross-browser way to distinguish between a file/folder from the File API so for now I'm using the no extension = folder heuristic
| // Use provided upload URL if passed in, otherwise construct | ||
| let uploadSessionUrl = url; | ||
| if (!uploadSessionUrl) { | ||
| uploadSessionUrl = `${this.uploadHost}/api/2.0/files/upload_sessions`; |
There was a problem hiding this comment.
Creating a url can be moved to base.js along with the other api one
| } | ||
|
|
||
| for (let i = 0; i < UPLOAD_PARALLELISM; i += 1) { | ||
| this.getNextChunk().then((chunk) => (chunk ? this.uploadChunk(chunk) : this.commitFile())).catch(() => { |
There was a problem hiding this comment.
Should catch just call this.uploadSessionErrorHandler?
There was a problem hiding this comment.
No, conceptually different - but this is unrecoverable though so I'll call the error callback
|
|
||
| // Read the blob as an ArrayBuffer so SHA1 can be calculated with Rusha | ||
| const fileReader = new FileReader(); | ||
| fileReader.addEventListener('load', (event: any) => { |
There was a problem hiding this comment.
event: Event & { target: EventTarget }
There was a problem hiding this comment.
What is this syntax exactly?
| resolve(chunk); | ||
| }); | ||
|
|
||
| fileReader.addEventListener('error', () => { |
There was a problem hiding this comment.
fileReader.addEventListener('error', reject) ?
| * | ||
| * @return {Promise} | ||
| */ | ||
| getNextChunk(): Promise<any> { |
- Files >50MB will be uploaded with the chunked uploads API by default - The 'chunked' Content Uploader option can be set to false to disable chunked uploads - Chunk upload failures due to rate limiting or network errors will be retried until success
Uh oh!
There was an error while loading. Please reload this page.