tus.mdx 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. ---
  2. sidebar_position: 2
  3. slug: /tus
  4. ---
  5. import Tabs from '@theme/Tabs';
  6. import TabItem from '@theme/TabItem';
  7. import UppyCdnExample from '/src/components/UppyCdnExample';
  8. # Tus
  9. The `@uppy/tus` plugin brings resumable file uploading with [Tus](http://tus.io)
  10. to Uppy by wrapping the [`tus-js-client`][].
  11. ## When should I use it?
  12. :::tip
  13. Not sure which uploader is best for you? Read
  14. “[Choosing the uploader you need](/docs/guides/choosing-uploader)”.
  15. :::
  16. [Tus][tus] is an open protocol for resumable uploads built on HTTP. This means
  17. accidentally closing your tab or losing connection let’s you continue, for
  18. instance, your 10GB upload instead of starting all over.
  19. Tus supports any language, any platform, and any network. It requires a client
  20. and server integration to work. You can checkout the client and server
  21. [implementations][] to find the server in your preferred language. You can store
  22. files on the Tus server itself, but you can also use service integrations (such
  23. as S3) to store files externally. If you don’t want to host your own server, see
  24. “[Are there hosted Tus servers?](#are-there-hosted-tus-servers)”.
  25. If you want reliable, resumable uploads: use `@uppy/tus` to connect to your Tus
  26. server in a few lines of code.
  27. ## Install
  28. <Tabs>
  29. <TabItem value="npm" label="NPM" default>
  30. ```shell
  31. npm install @uppy/tus
  32. ```
  33. </TabItem>
  34. <TabItem value="yarn" label="Yarn">
  35. ```shell
  36. yarn add @uppy/tus
  37. ```
  38. </TabItem>
  39. <TabItem value="cdn" label="CDN">
  40. <UppyCdnExample>
  41. {`
  42. import { Uppy, Tus } from "{{UPPY_JS_URL}}"
  43. new Uppy().use(Tus, { endpoint: 'https://tusd.tusdemo.net/files' })
  44. `}
  45. </UppyCdnExample>
  46. </TabItem>
  47. </Tabs>
  48. ## Use
  49. A quick overview of the complete API.
  50. ```js {10} showLineNumbers
  51. import Uppy from '@uppy/core';
  52. import Dashboard from '@uppy/dashboard';
  53. import Tus from '@uppy/tus';
  54. import '@uppy/core/dist/style.min.css';
  55. import '@uppy/dashboard/dist/style.min.css';
  56. new Uppy()
  57. .use(Dashboard, { inline: true, target: 'body' })
  58. .use(Tus, { endpoint: 'https://tusd.tusdemo.net/files/' });
  59. ```
  60. ### TypeScript
  61. If you want the `response` argument on the `upload-success` event and
  62. `file.response.body` to be typed, you have to pass a generic to the Uppy class.
  63. ```ts showLineNumbers
  64. // ...
  65. import Tus, { type TusBody } from '@uppy/tus';
  66. type MyMeta = {
  67. /* your added meta data */
  68. };
  69. const uppy = new Uppy<MyMeta, TusBody>().use(Tus, {
  70. endpoint: 'https://tusd.tusdemo.net/files/',
  71. });
  72. const [firstFile] = uppy.getFiles();
  73. // Correctly typed as XMLHttpRequest.
  74. // Populated after uppy.upload()
  75. firstFile.response.body.xhr;
  76. ```
  77. ## API
  78. ### Options
  79. :::info
  80. All options are passed to `tus-js-client` and we document the ones here that are
  81. required, added, or changed. This means you can also pass functions like
  82. [`onAfterResponse`](https://github.com/tus/tus-js-client/blob/master/docs/api.md#onafterresponse).
  83. We recommended taking a look at the
  84. [API reference](https://github.com/tus/tus-js-client/blob/master/docs/api.md)
  85. from `tus-js-client` to know what is supported.
  86. :::
  87. #### `id`
  88. A unique identifier for this plugin (`string`, default: `'Tus'`).
  89. #### `endpoint`
  90. URL of the tus server (`string`, default: `null`).
  91. #### `headers`
  92. An object or function returning an object with HTTP headers to send along
  93. requests (`object | function`, default: `null`).
  94. Keys are header names, values are header values.
  95. ```js
  96. const headers = {
  97. authorization: `Bearer ${window.getCurrentUserToken()}`,
  98. };
  99. ```
  100. Header values can also be derived from file data by providing a function. The
  101. function receives an [Uppy file][] and must return an object where the keys are header
  102. names, and values are header values.
  103. ```js
  104. const headers = (file) => {
  105. return {
  106. authorization: `Bearer ${window.getCurrentUserToken()}`,
  107. expires: file.meta.expires,
  108. };
  109. };
  110. ```
  111. #### `chunkSize`
  112. A number indicating the maximum size of a `PATCH` request body in bytes
  113. (`number`, default: `Infinity`). Note that this option only affects local
  114. browser uploads. If you need a max chunk size for remote (Companion) uploads,
  115. you must set the `chunkSize` Companion option as well.
  116. :::caution
  117. Do not set this value unless you are forced to. The two valid reasons are
  118. described in the
  119. [`tus-js-client` docs](https://github.com/tus/tus-js-client/blob/master/docs/api.md#chunksize).
  120. :::
  121. #### `withCredentials`
  122. Configure the requests to send Cookies using the
  123. [`xhr.withCredentials`](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials)
  124. property (`boolean`, default: `false`).
  125. The remote server must accept CORS and credentials.
  126. #### `retryDelays`
  127. When uploading a chunk fails, automatically try again after the defined
  128. millisecond intervals (`Array<number>`, default: `[0, 1000, 3000, 5000]`).
  129. By default, we first retry instantly; if that fails, we retry after 1 second; if
  130. that fails, we retry after 3 seconds, etc.
  131. Set to `null` to disable automatic retries, and fail instantly if any chunk
  132. fails to upload.
  133. #### `onBeforeRequest(req, file)`
  134. Behaves like the
  135. [`onBeforeRequest`](https://github.com/tus/tus-js-client/blob/master/docs/api.md#onbeforerequest)
  136. function from `tus-js-client` but with the added `file` argument.
  137. #### `onShouldRetry: (err, retryAttempt, options, next)`
  138. When an upload fails `onShouldRetry` is called with the error and the default
  139. retry logic as the last argument (`function`).
  140. The default retry logic is an
  141. [exponential backoff](https://en.wikipedia.org/wiki/Exponential_backoff)
  142. algorithm triggered on HTTP 429 (Too Many Requests) errors. Meaning if your
  143. server (or proxy) returns HTTP 429 because it’s being overloaded, @uppy/tus will
  144. find the ideal sweet spot to keep uploading without overloading.
  145. If you want to extend this functionality, for instance to retry on unauthorized
  146. requests (to retrieve a new authentication token):
  147. ```js
  148. import Uppy from '@uppy/core';
  149. import Tus from '@uppy/tus';
  150. new Uppy().use(Tus, {
  151. endpoint: '',
  152. async onBeforeRequest(req) {
  153. const token = await getAuthToken();
  154. req.setHeader('Authorization', `Bearer ${token}`);
  155. },
  156. onShouldRetry(err, retryAttempt, options, next) {
  157. if (err?.originalResponse?.getStatus() === 401) {
  158. return true;
  159. }
  160. return next(err);
  161. },
  162. async onAfterResponse(req, res) {
  163. if (res.getStatus() === 401) {
  164. await refreshAuthToken();
  165. }
  166. },
  167. });
  168. ```
  169. #### `allowedMetaFields`
  170. Pass an array of field names to limit the metadata fields that will be added to
  171. uploads as
  172. [Tus Metadata](https://tus.io/protocols/resumable-upload.html#upload-metadata)
  173. (`Array`, default: `null`).
  174. - Set it to `false` to not send any fields (or an empty array).
  175. - Set it to `['name']` to only send the `name` field.
  176. - Set it to `true` (the default) to send _all_ metadata fields.
  177. #### `limit`
  178. Limit the amount of uploads going on at the same time (`number`, default: `20`).
  179. Setting this to `0` means no limit on concurrent uploads (not recommended).
  180. ## Frequently Asked Questions
  181. :::info
  182. The Tus website has extensive [FAQ section](https://tus.io/faq.html), we
  183. recommend taking a look there as well if something is unclear.
  184. :::
  185. ### How is file meta data stored?
  186. Tus uses unique identifiers for the file names to prevent naming collisions. To
  187. still keep the meta data in place, Tus also uploads an extra `.info` file with
  188. the original file name and other meta data:
  189. ```json
  190. {
  191. "ID": "00007a99d16d4eeb5a3e3c080b6f69da+JHZavdqPSK4VMtarg2yYcNiP8t_kDjN51lBYMJdEyr_wqEotVl8ZBRBSTnWKWenZBwHvbLNz5tQXYp2N7Vdol.04ysQAuw__suTJ4IsCljj0rjyWA6LvV4IwF5P2oom2",
  192. "Size": 1679852,
  193. "SizeIsDeferred": false,
  194. "Offset": 0,
  195. "MetaData": {
  196. "filename": "cat.jpg",
  197. "filetype": "image/jpeg"
  198. },
  199. "IsPartial": false,
  200. "IsFinal": false,
  201. "PartialUploads": null,
  202. "Storage": {
  203. "Bucket": "your-bucket",
  204. "Key": "some-key",
  205. "Type": "s3store"
  206. }
  207. }
  208. ```
  209. ### How do I change files before sending them?
  210. If you want to change the file names, you want to do that in
  211. [`onBeforeFileAdded`](/docs/uppy#onbeforefileaddedfile-files).
  212. If you want to send extra headers with the request, use [`headers`](#headers) or
  213. [`onBeforeRequest`](#onbeforerequestreq-file).
  214. ### How do I change (or move) files after sending them?
  215. If you want to preserve files names, extract meta data, or move files to a
  216. different place you generally can with hooks or events. It depends on the Tus
  217. server you use how it’s done exactly. [`tusd`][], for instance, exposes
  218. [hooks](https://github.com/tus/tusd/blob/master/docs/hooks.md) and
  219. [`tus-node-server`](https://github.com/tus/tus-node-server) has
  220. [events](https://github.com/tus/tus-node-server#events).
  221. ### Which server do you recommend?
  222. [Transloadit](https://transloadit.com) runs [`tusd`][] in production, where it
  223. serves millions of requests globally. So we recommend `tusd` as battle-tested
  224. from our side, but other companies have had success with other
  225. [implementations][] so it depends on your needs.
  226. ### Are there hosted Tus servers?
  227. All [Transloadit plans](https://transloadit.com/pricing) come with a hosted
  228. [`tusd`][] server. You don’t have to do anything to leverage it, using
  229. [`@uppy/transloadit`](/docs/transloadit) automatically uses Tus under the hood.
  230. ### Why Tus instead of directly uploading to AWS S3?
  231. First: reliable, resumable uploads. This means accidentally closing your tab or
  232. losing connection let’s you continue, for instance, your 10GB upload instead of
  233. starting all over.
  234. Tus is also efficient with lots of files (such as 8K) and large files. Uploading
  235. to AWS S3 directly from the client also introduces quite a bit of overhead, as
  236. more requests are needed for the flow to work.
  237. [`tus-js-client`]: https://github.com/tus/tus-js-client
  238. [uppy file]: /docs/uppy#working-with-uppy-files
  239. [tus]: https://tus.io/
  240. [`tusd`]: https://github.com/tus/tusd
  241. [implementations]: https://tus.io/implementations.html