xhr.mdx 11 KB

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