xhr.mdx 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. ---
  2. sidebar_position: 5
  3. slug: /xhr-upload
  4. ---
  5. import Tabs from '@theme/Tabs';
  6. import TabItem from '@theme/TabItem';
  7. import UppyCdnExample from '/src/components/UppyCdnExample';
  8. # XHR
  9. The `@uppy/xhr-upload` plugin is for regular uploads to a HTTP server.
  10. ## When should I use it?
  11. :::tip
  12. Not sure which uploader is best for you? Read
  13. “[Choosing the uploader you need](/docs/guides/choosing-uploader)”.
  14. :::
  15. When you have an existing HTTP server and you don’t need Transloadit services or
  16. want to run a [tus][] server. Note that it’s still possible to use [tus][]
  17. without running an extra server by integrating tus into your existing one. For
  18. instance, if you have a Node.js server (or server-side framework like Next.js)
  19. you could integrate [tus-node-server][].
  20. ## Install
  21. <Tabs>
  22. <TabItem value="npm" label="NPM" default>
  23. ```shell
  24. npm install @uppy/xhr-upload
  25. ```
  26. </TabItem>
  27. <TabItem value="yarn" label="Yarn">
  28. ```shell
  29. yarn add @uppy/xhr-upload
  30. ```
  31. </TabItem>
  32. <TabItem value="cdn" label="CDN">
  33. <UppyCdnExample>
  34. {`
  35. import { Uppy, XHRUpload } from "{{UPPY_JS_URL}}"
  36. new Uppy().use(XHRUpload, { endpoint: 'https://tusd.tusdemo.net/files' })
  37. `}
  38. </UppyCdnExample>
  39. </TabItem>
  40. </Tabs>
  41. ## Use
  42. A quick overview of the complete API.
  43. ```js {10} showLineNumbers
  44. import Uppy from '@uppy/core';
  45. import Dashboard from '@uppy/dashboard';
  46. import XHR from '@uppy/xhr-upload';
  47. import '@uppy/core/dist/style.min.css';
  48. import '@uppy/dashboard/dist/style.min.css';
  49. new Uppy()
  50. .use(Dashboard, { inline: true, target: 'body' })
  51. .use(XHR, { endpoint: 'https://your-domain.com/upload' });
  52. ```
  53. ## API
  54. ### Options
  55. #### `id`
  56. A unique identifier for this plugin (`string`, default: `'XHRUpload'`).
  57. #### `endpoint`
  58. URL of the HTTP server (`string`, default: `null`).
  59. #### `method`
  60. Configures which HTTP method to use for the upload (`string`, default:
  61. `'POST'`).
  62. :::note
  63. Uppy is not following the standard and will uppercase the method name. This
  64. behavior will be removed in a future version to align Uppy with the web APIs.
  65. :::
  66. #### `formData`
  67. Configures whether to use a multipart form upload, using [FormData][]
  68. (`boolean`, default: `true`).
  69. This works similarly to using a `<form>` element with an `<input type="file">`
  70. for uploads. When set to `true`, file metadata is also sent to the endpoint as
  71. separate form fields. When set to `false`, only the file contents are sent.
  72. #### `fieldName`
  73. When [`formData`](#formData-true) is set to true, this is used as the form field
  74. name for the file to be uploaded.
  75. It defaults to `'files[]'` if `bundle` option is set to `true`, otherwise it
  76. defaults to `'file'`.
  77. #### `allowedMetaFields`
  78. Pass an array of field names to limit the metadata fields that will be added to
  79. upload.
  80. - Set this to an empty array `[]` to not send any fields.
  81. - Set this to `['name']` to only send the `name` field.
  82. - Set this to `null` (the default) to send _all_ metadata fields.
  83. If the [`formData`](#formData-true) option is set to false, `metaFields` is
  84. ignored.
  85. #### `headers`
  86. An object containing HTTP headers to use for the upload request. Keys are header
  87. names, values are header values.
  88. ```js
  89. const headers = {
  90. authorization: `Bearer ${window.getCurrentUserToken()}`,
  91. };
  92. ```
  93. Header values can also be derived from file data by providing a function. The
  94. function receives an [Uppy file][] and must return an object where the keys are
  95. header names, and values are header values.
  96. ```js
  97. const headers = (file) => {
  98. return {
  99. authorization: `Bearer ${window.getCurrentUserToken()}`,
  100. expires: file.meta.expires,
  101. };
  102. };
  103. ```
  104. :::note
  105. The function syntax is not available when [`bundle`](#bundle) is set to `true`.
  106. :::
  107. #### `bundle`
  108. Send all files in a single multipart request (`boolean`, default: `false`).
  109. All files will be appended to the provided `fieldName` field in the request.
  110. :::caution
  111. When `bundle` is set to `true`:
  112. - [`formData`](#formData-true) must also be set to `true`.
  113. - Uppy won’t be able to bundle remote files (such as Google Drive) and will
  114. throw an error in this case.
  115. - Only [global uppy metadata](/docs/uppy/#meta) is sent to the endpoint.
  116. Individual per-file metadata is ignored.
  117. :::
  118. To upload files on different fields, use
  119. [`uppy.setFileState()`](/docs/uppy#uppy-setFileState-fileID-state) to set the
  120. `xhrUpload.fieldName` property on the file:
  121. ```js
  122. uppy.setFileState(fileID, {
  123. xhrUpload: { fieldName: 'pic0' },
  124. });
  125. ```
  126. #### `validateStatus`
  127. Check if the response was successful (`function`, default:
  128. `(status, responseText, response) => boolean`).
  129. - By default, responses with a 2xx HTTP status code are considered successful.
  130. - When `true`, [`getResponseData()`](#getResponseData-responseText-response)
  131. will be called and the upload will be marked as successful.
  132. - When `false`, both
  133. [`getResponseData()`](#getResponseData-responseText-response) and
  134. [`getResponseError()`](#getResponseError-responseText-response) will be called
  135. and the upload will be marked as unsuccessful.
  136. ##### Parameters
  137. - The `statusCode` is the numeric HTTP status code returned by the endpoint.
  138. - The `responseText` is the XHR endpoint response as a string.
  139. - `response` is the [XMLHttpRequest][] object.
  140. :::note
  141. This option is only used for **local** uploads. Uploads from remote providers
  142. like Google Drive or Instagram do not support this and will always use the
  143. default.
  144. :::
  145. #### `getResponseData`
  146. Extract the response data from the successful upload (`function`, default:
  147. `(responseText, response) => void`).
  148. - `responseText` is the XHR endpoint response as a string.
  149. - `response` is the [XMLHttpRequest][] object.
  150. JSON is handled automatically, so you should only use this if the endpoint
  151. responds with a different format. For example, an endpoint that responds with an
  152. XML document:
  153. ```js
  154. function getResponseData(responseText, response) {
  155. const parser = new DOMParser();
  156. const xmlDoc = parser.parseFromString(responseText, 'text/xml');
  157. return {
  158. url: xmlDoc.querySelector('Location').textContent,
  159. };
  160. }
  161. ```
  162. :::note
  163. This response data will be available on the file’s `.response` property and will
  164. be emitted in the [`upload-success`][uppy.upload-success] event.
  165. :::
  166. :::note
  167. When uploading files from remote providers such as Dropbox or Instagram,
  168. Companion sends upload response data to the client. This is made available in
  169. the `getResponseData()` function as well. The `response` object from Companion
  170. has some properties named after their [XMLHttpRequest][] counterparts.
  171. :::
  172. #### `getResponseError`
  173. Extract the error from the failed upload (`function`, default:
  174. `(responseText, response) => void`).
  175. For example, if the endpoint responds with a JSON object containing a
  176. `{ message }` property, this would show that message to the user:
  177. ```js
  178. function getResponseError(responseText, response) {
  179. return new Error(JSON.parse(responseText).message);
  180. }
  181. ```
  182. #### `responseUrlFieldName`
  183. The field name containing the location of the uploaded file (`string`, default:
  184. `'url'`).
  185. This is returned by [`getResponseData()`](#getResponseData).
  186. #### `timeout: 30 * 1000`
  187. Abort the connection if no upload progress events have been received for this
  188. milliseconds amount (`number`, default: `30_000`).
  189. Note that unlike the [`XMLHttpRequest.timeout`][xhr.timeout] property, this is a
  190. timer between progress events: the total upload can take longer than this value.
  191. Set to `0` to disable this check.
  192. #### `limit`
  193. The maximum amount of files to upload in parallel (`number`, default: `5`).
  194. #### `responseType`
  195. The response type expected from the server, determining how the `xhr.response`
  196. property should be filled (`string`, default: `'text'`).
  197. The `xhr.response` property can be accessed in a custom
  198. [`getResponseData()`](#getResponseData-responseText-response) callback. This
  199. option sets the [`XMLHttpRequest.responseType`][xhr.responsetype] property. Only
  200. `''`, `'text'`, `'arraybuffer'`, `'blob'` and `'document'` are widely supported
  201. by browsers, so it’s recommended to use one of those.
  202. #### `withCredentials`
  203. Indicates whether cross-site Access-Control requests should be made using
  204. credentials (`boolean`, default: `false`).
  205. #### `locale: {}`
  206. ```js
  207. export default {
  208. strings: {
  209. // Shown in the Informer if an upload is being canceled because it stalled for too long.
  210. timedOut: 'Upload stalled for %{seconds} seconds, aborting.',
  211. },
  212. };
  213. ```
  214. ## Frequently Asked Questions
  215. ### How to send along meta data with the upload?
  216. When using XHRUpload with [`formData: true`](#formData-true), file metadata is
  217. sent along with each upload request. You can set metadata for a file using
  218. [`uppy.setFileMeta(fileID, data)`](/docs/uppy#uppy-setFileMeta-fileID-data), or
  219. for all files simultaneously using
  220. [`uppy.setMeta(data)`](/docs/uppy#uppy-setMeta-data).
  221. It may be useful to set metadata depending on some file properties, such as the
  222. size. You can use the [`file-added`](/docs/uppy/#file-added) event and the
  223. [`uppy.setFileMeta(fileID, data)`](/docs/uppy#uppy-setFileMeta-fileID-data)
  224. method to do this:
  225. ```js
  226. uppy.on('file-added', (file) => {
  227. uppy.setFileMeta(file.id, {
  228. size: file.size,
  229. });
  230. });
  231. ```
  232. Now, a form field named `size` will be sent along to the
  233. [`endpoint`](#endpoint-39-39) once the upload starts.
  234. By default, all metadata is sent, including Uppy’s default `name` and `type`
  235. metadata. If you do not want the `name` and `type` metadata properties to be
  236. sent to your upload endpoint, you can use the [`metaFields`](#metaFields-null)
  237. option to restrict the field names that should be sent.
  238. ```js
  239. uppy.use(XHRUpload, {
  240. // Only send our own `size` metadata field.
  241. allowedMetaFields: ['size'],
  242. });
  243. ```
  244. ### How to upload to a PHP server?
  245. The XHRUpload plugin works similarly to a `<form>` upload. You can use the
  246. `$_FILES` variable on the server to work with uploaded files. See the PHP
  247. documentation on [Handling file uploads][php.file-upload].
  248. The default form field for file uploads is `files[]`, which means you have to
  249. access the `$_FILES` array as described in [Uploading many files][php.multiple]:
  250. ```php
  251. <?php
  252. // upload.php
  253. $files = $_FILES['files'];
  254. $file_path = $files['tmp_name'][0]; // temporary upload path of the first file
  255. $file_name = $_POST['name']; // desired name of the file
  256. move_uploaded_file($file_path, './img/' . basename($file_name)); // save the file in `img/`
  257. ```
  258. Note how we are using `$_POST['name']` instead of `$my_file['name']`.
  259. `$my_file['name']` has the original name of the file on the user’s device.
  260. `$_POST['name']` has the `name` metadata value for the uploaded file, which can
  261. be edited by the user using the [Dashboard](/docs/dashboard).
  262. Set a custom `fieldName` to make working with the `$_FILES` array a bit less
  263. convoluted:
  264. ```js
  265. // app.js
  266. uppy.use(XHRUpload, {
  267. endpoint: '/upload.php',
  268. fieldName: 'my_file',
  269. });
  270. ```
  271. ```php
  272. <?php
  273. // upload.php
  274. $my_file = $_FILES['my_file'];
  275. $file_path = $my_file['tmp_name']; // temporary upload path of the file
  276. $file_name = $_POST['name']; // desired name of the file
  277. move_uploaded_file($file_path, $_SERVER['DOCUMENT_ROOT'] . '/img/' . basename($file_name)); // save the file at `img/FILE_NAME`
  278. ```
  279. [formdata]: https://developer.mozilla.org/en-US/docs/Web/API/FormData
  280. [xmlhttprequest]:
  281. https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest
  282. [xhr.timeout]:
  283. https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/timeout
  284. [xhr.responsetype]:
  285. https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseType
  286. [uppy.upload-success]: /docs/uppy/#upload-success
  287. [uppy file]: /docs/uppy#working-with-uppy-files
  288. [php.file-upload]: https://secure.php.net/manual/en/features.file-upload.php
  289. [php.multiple]:
  290. https://secure.php.net/manual/en/features.file-upload.multiple.php
  291. [tus-node-server]: https://github.com/tus/tus-node-server
  292. [tus]: https://tus.io/