diff --git a/docs/api.md b/docs/api.md index ef36def5..5d28a921 100644 --- a/docs/api.md +++ b/docs/api.md @@ -166,6 +166,18 @@ metadata: { } ``` +#### metadataForPartialUploads + +_Default value:_ `{}` + +An object with string values used as additional meta data for partial uploads. When parallel uploads are enabled via `parallelUploads`, tus-js-client creates multiple partial uploads. The values from `metadata` are not passed to these partial uploads but only passed to the final upload, which is the concatentation of the partial uploads. In contrast, the values from `metadataForPartialUploads` are only passed to the partial uploads and not the final upload. This option has no effect if parallel uploads are not enabled. Can be used to associate partial uploads to a user, for example: + +```js +metadataForPartialUploads: { + userId: "1234567" +} +``` + #### uploadUrl _Default value:_ `null` @@ -234,7 +246,7 @@ X-Request-ID: fe51f777-f23e-4ed9-97d7-2785cc69f961 _Default value:_ `1` -A number indicating how many parts should be uploaded in parallel. If this number is not `1`, the input file will be split into multiple parts, where each part is uploaded individually in parallel. The value of `parallelUploads` determines the number of parts. Using `parallelUploadBoundaries` the size of each part can be changed. After all parts have been uploaded, the [`concatenation` extension](https://tus.io/protocols/resumable-upload.html#concatenation) will be used to concatenate all the parts together on the server-side, so the tus server must support this extension. This option should not be used if the input file is a streaming resource. +A number indicating how many parts should be uploaded in parallel. If this number is not `1`, the input file will be split into multiple parts, where each part is uploaded individually in parallel. The value of `parallelUploads` determines the number of parts. Using `parallelUploadBoundaries` the size of each part can be changed. After all parts have been uploaded, the [`concatenation` extension](https://tus.io/protocols/resumable-upload.html#concatenation) will be used to concatenate all the parts together on the server-side, so the tus server must support this extension. This option should not be used if the input file is a streaming resource. By default, the values from `metadata` are not passed to the partial uploads and only used for the final upload where the parts are concatenated together again. The `metadataForPartialUploads` option can be used to set meta data specifically for partial uploads. The idea behind this option is that you can use multiple HTTP requests in parallel to better utilize the full capacity of the network connection to the tus server. If you want to use it, please evaluate it under real world situations to see if it actually improves your upload performance. In common browser session, we were not able to find a performance improve for the average user. diff --git a/lib/index.d.ts b/lib/index.d.ts index cb093d35..3ef96c9f 100644 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -26,6 +26,7 @@ interface UploadOptions { uploadUrl?: string | null metadata?: { [key: string]: string } + metadataForPartialUploads?: { [key: string]: string } fingerprint?: (file: File, options: UploadOptions) => Promise uploadSize?: number | null diff --git a/lib/index.test-d.ts b/lib/index.test-d.ts index 1209dedc..6f1f399d 100644 --- a/lib/index.test-d.ts +++ b/lib/index.test-d.ts @@ -19,6 +19,9 @@ const upload = new tus.Upload(file, { metadata: { filename: 'foo.txt', }, + metadataForPartialUploads: { + userId: 'foo123bar', + }, onProgress: (bytesSent: number, bytesTotal: number) => { const percentage = ((bytesSent / bytesTotal) * 100).toFixed(2) console.log(bytesSent, bytesTotal, `${percentage}%`) diff --git a/lib/upload.js b/lib/upload.js index fe3f5a44..6c0218e1 100644 --- a/lib/upload.js +++ b/lib/upload.js @@ -12,6 +12,7 @@ const defaultOptions = { uploadUrl: null, metadata: {}, + metadataForPartialUploads: {}, fingerprint: null, uploadSize: null, @@ -331,7 +332,7 @@ class BaseUpload { parallelUploads: 1, // Reset this option as we are not doing a parallel upload. parallelUploadBoundaries: null, - metadata: {}, + metadata: this.options.metadataForPartialUploads, // Add the header to indicate the this is a partial upload. headers: { ...this.options.headers, diff --git a/test/spec/test-parallel-uploads.js b/test/spec/test-parallel-uploads.js index fe4cb529..db7d46d9 100644 --- a/test/spec/test-parallel-uploads.js +++ b/test/spec/test-parallel-uploads.js @@ -76,6 +76,9 @@ describe('tus', () => { metadata: { foo: 'hello', }, + metadataForPartialUploads: { + test: 'world', + }, onProgress() {}, onSuccess: waitableFunction(), fingerprint: () => Promise.resolve('fingerprinted'), @@ -92,7 +95,7 @@ describe('tus', () => { expect(req.requestHeaders['Tus-Resumable']).toBe('1.0.0') expect(req.requestHeaders['Upload-Length']).toBe(5) expect(req.requestHeaders['Upload-Concat']).toBe('partial') - expect(req.requestHeaders['Upload-Metadata']).toBeUndefined() + expect(req.requestHeaders['Upload-Metadata']).toBe('test d29ybGQ=') // world req.respondWith({ status: 201, @@ -108,7 +111,7 @@ describe('tus', () => { expect(req.requestHeaders['Tus-Resumable']).toBe('1.0.0') expect(req.requestHeaders['Upload-Length']).toBe(6) expect(req.requestHeaders['Upload-Concat']).toBe('partial') - expect(req.requestHeaders['Upload-Metadata']).toBeUndefined() + expect(req.requestHeaders['Upload-Metadata']).toBe('test d29ybGQ=') // world req.respondWith({ status: 201, @@ -188,7 +191,7 @@ describe('tus', () => { expect(req.requestHeaders['Upload-Concat']).toBe( 'final;https://tus.io/uploads/upload1 https://tus.io/uploads/upload2', ) - expect(req.requestHeaders['Upload-Metadata']).toBe('foo aGVsbG8=') + expect(req.requestHeaders['Upload-Metadata']).toBe('foo aGVsbG8=') // hello req.respondWith({ status: 201,