项目
版本

Uppy XHR 上传

@uppy/xhr-upload 插件用于向 HTTP 服务器进行常规上传。

何时使用?

当您已有 HTTP 服务器,且不需要 Transloadit 服务或不想运行 tus 服务器时。请注意,即使不运行额外的服务器,通过将 tus 集成到现有服务器中,仍然可以使用 tus. 例如,如果您有一个 Node.js 服务器(或服务器端框架如 Next.js),您可以集成 tus-node-server

安装

  • npm

    npm install @uppy/xhr-upload
    
  • yarn

    yarn add @uppy/xhr-upload
    
  • CDN

    <!-- 1. Add CSS to `<head>` -->
    <link href="https://releases.transloadit.com/uppy/v3.27.3/uppy.min.css" rel="stylesheet">
    
    <!-- 2. Initialize -->
    <div id="uppy"></div>
    
    <script type="module">
        import { Uppy, XHRUpload } from "https://releases.transloadit.com/uppy/v3.27.3/uppy.min.mjs"
        new Uppy().use(XHRUpload, { endpoint: 'https://tusd.tusdemo.net/files' })
    </script>
    

使用

API 的快速概览。

import Uppy from "@uppy/core";
import Dashboard from "@uppy/dashboard";
import XHR from "@uppy/xhr-upload";

import "@uppy/core/dist/style.min.css";
import "@uppy/dashboard/dist/style.min.css";

new Uppy()
  .use(Dashboard, { inline: true, target: "body" })
  .use(XHR, { endpoint: "https://your-domain.com/upload" });

API

选项

id

此插件的唯一标识符( string,默认:'XHRUpload' )。

endpoint

HTTP 服务器的 URL( string,默认:null )。

method

配置用于上传的 HTTP 方法( string,默认:'POST' )。

注意

Uppy 目前未遵循标准,会将方法名称大写。此行为将在未来版本中移除,以使 Uppy 与 Web API 对齐。

formData

配置是否使用 multipart 表单上传,使用 FormDataboolean,默认:true )。

这类似于使用包含 <input type="file"><form> 元素进行上传。当设置为 true 时,文件元数据也会作为单独的表单项发送到端点。设为 false 时,则仅发送文件内容。

fieldName

formData 设置为 true 时,用作要上传的文件的表单字段名 。

如果 bundle 选项设置为 true ,则默认为 'files[]' ,否则默认为 'file'

allowedMetaFields

传递一个字段名称数组来限制将添加到上传中的元数据字段。

  • 设置为空数组 [] 表示不发送任何字段。
  • 设置为 ['name'] 表示只发送 name 字段。
  • 设置为 null(默认值)表示发送所有元数据字段。

如果 formData 选项设置为 false,则忽略 metaFields

headers

一个对象,包含用于上传请求的 HTTP 头。键是头部名称,值是头部值。

const headers = {
  authorization: `Bearer ${window.getCurrentUserToken()}`,
};

头部值也可以从文件数据派生,通过提供一个函数。该函数接收一个 Uppy 文件 ,并必须返回一个对象,其中键是头部名称,值是头部值。

const headers = (file) => {
  return {
    authorization: `Bearer ${window.getCurrentUserToken()}`,
    expires: file.meta.expires,
  };
};

注意

[bundle](#bundle) 设置为 true 时,函数语法不可用。

bundle

将所有文件在一个 multipart 请求中发送( boolean,默认:false )。

所有文件将附加到请求中提供的 fieldName 字段中。

要在不同的字段上上传文件,请使用 uppy.setFileState() 来设置文件上的 xhrUpload.fieldName 属性:

uppy.setFileState(fileID, {
  xhrUpload: { fieldName: "pic0" },
});

validateStatus

检查响应是否成功( function,默认:(status, responseText, response) => boolean )。

  • 默认情况下,具有 2xx HTTP 状态码的响应被认为是成功的。
  • 当为 true 时,将会调用 getResponseData() 并且上传将被标记为成功。
  • 当为 false 时,将会调用 两者 getResponseData()getResponseError() 并且上传将被标记为不成功。
参数
  • statusCode 是端点返回的数字 HTTP 状态码。
  • responseText 是 XHR 端点响应的字符串形式。
  • responseXMLHttpRequest 对象。

注意

此选项仅用于本地上传。来自 Google Drive 或 Instagram 等远程提供商的上传不支持此功能,将始终使用默认值。

getResponseData

从成功的上传中提取响应数据( function,默认:(responseText, response) => void )。

  • responseText 是 XHR 端点响应的字符串形式。
  • responseXMLHttpRequest 对象。

JSON 已经自动处理,因此仅在端点以不同格式响应时才应使用此方法。例如,响应 XML 文档的端点:

function getResponseData(responseText, response) {
  const parser = new DOMParser();
  const xmlDoc = parser.parseFromString(responseText, "text/xml");
  return {
    url: xmlDoc.querySelector("Location").textContent,
  };
}

注意

此响应数据将在文件的 .response 属性上可用,并将在 [upload-success][uppy.upload-success] 事件中发出。

注意 从 Dropbox 或 Instagram 等远程提供商上传文件时,Companion 会将上传响应数据发送到客户端。这也会在 getResponseData() 函数中可用。来自 Companion 的 response 对象具有一些以其 XMLHttpRequest 对应项命名的属性 。

getResponseError

从失败的上传中提取错误( function,默认:(responseText, response) => void )。

例如,如果端点响应包含一个含 { message } 属性的 JSON 对象,这将向用户显示该消息:

function getResponseError(responseText, response) {
  return new Error(JSON.parse(responseText).message);
}

responseUrlFieldName

包含已上传文件位置的字段名( string,默认:'url' )。

这是由 getResponseData() 返回的。

timeout: 30 * 1000

如果在这些毫秒内未接收到任何上传进度事件,则中止连接( number,默认:30_000 )。

请注意,与 XMLHttpRequest.timeout 属性不同,这是一个进度事件之间的计时器:整个上传过程可以比这个值更长。设置为 0 可以禁用此检查。

limit

并行上传的最大文件数量(number,默认:5)。

responseType

期望从服务器接收的响应类型,确定如何填充 xhr.response 属性(string,默认:'text')。

可以在自定义的 getResponseData() 回调中访问 xhr.response 属性。此选项设置了 XMLHttpRequest.responseType 属性。只有 '''text''arraybuffer''blob''document' 被浏览器广泛支持,因此建议使用其中之一。

withCredentials

指示跨站点访问控制请求是否应使用凭据( boolean,默认:false )。

`locale:

export default {
  strings: {
    // 如果上传因长时间暂停而被取消,在 Informer 中显示。
    timedOut: "上传暂停了 %{seconds} 秒,正在中止。",
  },
};

常见问题解答

如何随上传一起发送元数据?

使用 XHRUpload 时带有 formData: true,文件元数据会随每个上传请求一起发送。您可以使用 uppy.setFileMeta(fileID, data) ,或对所有文件同时使用 uppy.setMeta(data) 来设置文件元数据 。

根据某些文件属性(如大小)设置元数据可能很有用。您可以使用 file-added 事件和 uppy.setFileMeta(fileID, data) 方法来实现这一点:

当文件被添加时,通过监听 file-added 事件,你可以往文件元数据中添加额外信息:

uppy.on('file-added', (file) => {
	uppy.setFileMeta(file.id, {
		size: file.size,
	});
});

现在,一旦上传开始,名为 size 的表单字段将会和文件一起发送到 [上传端点] 。

默认情况下,所有元数据都会被发送,包括 Uppy 的默认 nametype 元数据。如果你不希望 nametype 这两个元数据属性被发送到你的上传端点,可以使用 metaFields 选项来限制应该发送的字段名。

uppy.use(XHRUpload, {
  // 只发送我们自定义的 `size` 元数据字段。
  allowedMetaFields: ["size"],
});

如何上传到 PHP 服务器?

XHRUpload 插件的工作方式类似于 <form> 上传。在服务器端,你可以使用 $_FILES 变量来处理上传的文件。参阅 PHP 文档关于 处理文件上传 的部分。

文件上传的默认表单字段是 files[],这意味着你需要按照 上传多个文件 中描述的方式来访问 $_FILES 数组:

<?php
// upload.php
$files = $_FILES['files'];
$file_path = $files['tmp_name'][0]; // 文件的临时上传路径
$file_name = $_POST['name']; // 文件的期望名称
move_uploaded_file($file_path, './img/' . basename($file_name)); // 将文件保存在 `img/` 目录下

注意我们使用了 $_POST['name'] 而不是 $my_file['name']$my_file['name'] 是用户设备上文件的原始名称。而 $_POST['name'] 则是上传文件的 name 元数据值,用户可以在 Dashboard 中编辑它。

设置一个自定义的 fieldName 可以让处理 $_FILES 数组变得不那么复杂:

// app.js
uppy.use(XHRUpload, {
  endpoint: "/upload.php",
  fieldName: "my_file",
});
<?php
// upload.php
$my_file = $_FILES['my_file'];
$file_path = $my_file['tmp_name']; // 文件的临时上传路径
$file_name = $_POST['name']; // 文件的期望名称
move_uploaded_file($file_path, $_SERVER['DOCUMENT_ROOT'] . '/img/' . basename($file_name)); // 将文件保存在服务器根目录下的 `img/` 目录中
在本文档中