上传 Upload

在您的服务器或外部提供商上上传任何类型的文件。

上传插件是 Strapi 管理面板中默认提供的媒体库插件的后端。使用管理面板中的媒体库或直接使用上传 API,您可以上传任何类型的文件以供 Strapi 应用程序使用。

默认情况下,Strapi 提供了一个 提供程序,用于将文件上传到本地目录,默认情况下,该目录在您的 Strapi 项目中为“public/uploads/”。如果您想将文件上传到其他位置,可以使用其他提供程序。

Strapi 维护的提供商包括:

配置

本节详细介绍了默认上传提供商的配置选项。如果使用其他提供商(例如 AWS S3 或 Cloudinary),请参阅该提供商文档中的可用配置参数。

本地服务器

默认情况下,Strapi 接受本地上传文件的 localServer 配置。这些将作为 koa-static 的选项传递。

您可以通过创建或编辑 ./config/plugins.js 文件来提供它们。以下示例设置了“max-age”标头。

js
./config/plugins.js
js
module.exports = ({ env }) => ({
  upload: {
    config: {
      providerOptions: {
        localServer: {
          maxage: 300000
        },
      },
    },
  },
})

最大文件大小

目前,负责解析请求的 Strapi 中间件需要配置为支持大于默认值 200MB 的文件大小,此外还需要将提供商选项传递给上传插件以设置 sizeLimit。

您可能还需要调整任何上游代理、负载平衡器或防火墙以允许更大的文件大小。
(例如 Nginx 有一个名为 client_max_body_size 的配置设置,由于其默认值仅为 1mb,因此需要进行调整。)

我们使用的库是 koa-body,它使用 node-formidable 库来处理文件。

您可以通过在 ./config/middlewares.js 中的 body 中间件 配置中设置来直接将配置传递给中间件:

js
./config/middlewares.js
js
module.exports = [
  // ...
  {
    name: 'strapi::body',
    config: {
      formLimit: '256mb', // modify form body
      jsonLimit: '256mb', // modify JSON body
      textLimit: '256mb', // modify text body
      formidable: {
        maxFileSize: 250 * 1024 * 1024, // multipart data, modify here limit of uploaded file size
      },
    },
  },
  // ...
]

除了中间件配置之外,你还可以在 ./config/plugins.js 中的插件配置中传递 sizeLimit,它是一个以字节为单位的整数:

js
./config/plugins.js
js
module.exports = {
  // ...
  upload: {
    config: {
      sizeLimit: 250 * 1024 * 1024 // 256mb in bytes
    }
  }
}

上传请求超时

默认情况下,strapi.server.httpServer.requestTimeout 的值设置为 330 秒。这包括上传。为了让网络连接较慢的用户能够上传大文件,可能需要增加此超时限制。建议的方法是设置 config/server.js|ts 文件中的 http.serverOptions.requestTimeout 参数(请参阅 服务器配置。 另一种方法是在 Strapi 启动前运行的 bootstrap 函数中设置 requestTimeout 值。这在需要以编程方式更改的情况下很有用 - 例如,暂时禁用并重新启用它:

js
./index.js
js
module.exports = {
  // ...
  bootstrap({ strapi }) {
    // Set the requestTimeout to 1,800,000 milliseconds (30 minutes):
    strapi.server.httpServer.requestTimeout = 30 * 60 * 1000
  },
}

响应式图像

在设置面板中启用“启用响应式友好上传”设置后,插件将生成以下响应式图像尺寸:

名称最大尺寸
1000px
750px
500px

这些尺寸可以在 ./config/plugins.js 中覆盖:

js
./config/plugins.js
js
module.exports = ({ env }) => ({
  upload: {
    config: {
      breakpoints: {
        xlarge: 1920,
        large: 1000,
        medium: 750,
        small: 500,
        xsmall: 64
      },
    },
  },
})

断点更改仅适用于新图像,现有图像将不会调整大小或生成新尺寸。

Endpoints

方法路径描述
GET/api/upload/files获取文件列表
GET/api/upload/files/:id获取特定文件
POST/api/upload上传文件
POST/api/upload?id=x更新文件信息
DELETE/api/upload/files/:id删除文件

文件夹 是管理面板功能,不属于 REST 或 GraphQL API。通过 REST 或 GraphQL API 上传的文件位于自动创建的“API 上传”文件夹中。

示例

上传文件

将一个或多个文件上传到您的应用程序。

接受以下参数:

  • files:要上传的文件。值可以是缓冲区或流。
html
BROWSER
html
<form>
  <!-- Can be multiple files -->
  <input type="file" name="files" />
  <input type="submit" value="Submit" />
</form>

<script type="text/javascript">
  const form = document.querySelector('form');

  form.addEventListener('submit', async (e) => {
    e.preventDefault();

    await fetch('/api/upload', {
      method: 'post',
      body: new FormData(e.target)
    });
  });
</script>

您必须在请求正文中发送 FormData。

上传条目文件

上传一个或多个将链接到特定条目的文件。

接受以下参数:

参数描述
files要上传的文件。值可以是缓冲区或流。
path(可选)将上传文件到的文件夹(仅支持 strapi-provider-upload-aws-s3)。
refId将链接到文件的条目的 ID。
ref将链接到文件的模型的唯一 ID (uid)(请参阅下文了解更多信息)。
source(可选)模型所在的插件的名称。
field将精确链接到文件的条目的字段。

例如,给定“Restaurant”模型属性:

./src/api/restaurant/content-types/restaurant/schema.json
json
{
  // ...
  "attributes": {
    "name": {
      "type": "string"
    },
    "cover": {
      "type": "media",
      "multiple": false
    }
  }
// ...
}

对应的代码是:

html
<form>
  <!-- Can be multiple files if you setup "collection" instead of "model" -->
  <input type="file" name="files" />
  <input type="text" name="ref" value="api::restaurant.restaurant" />
  <input type="text" name="refId" value="5c126648c7415f0c0ef1bccd" />
  <input type="text" name="field" value="cover" />
  <input type="submit" value="Submit" />
</form>

<script type="text/javascript">
  const form = document.querySelector('form');

  form.addEventListener('submit', async (e) => {
    e.preventDefault();

    await fetch('/api/upload', {
      method: 'post',
      body: new FormData(e.target)
    });
  });
</script>

您必须在请求正文中发送 FormData。

在创建条目时上传文件

您还可以在创建条目时添加文件。

例如,给定“Restaurant”模型属性:

./src/api/restaurant/content-types/restaurant/schema.json
json
{
  // ...
  "attributes": {
    "name": {
      "type": "string"
    },
    "cover": {
      "type": "media",
      "multiple": false
    }
  }
  // ...
}

相应的代码为:

html
<form>
  <!-- Can be multiple files if you setup "collection" instead of "model" -->
  <input type="text" name="name" />
  <input type="file" name="cover" />
  <input type="submit" value="Submit" />
</form>

<script type="text/javascript">
  const form = document.querySelector('form');

  form.addEventListener('submit', async (e) => {
    e.preventDefault();

    const data = {};
    const formData = new FormData();

    form.elements
      .forEach(({ name, type, value, files, ...element }) => {
        if (!['submit', 'file'].includes(type)) {
          data[name] = value;
        } else if (type === 'file') {
          files.forEach((file) => {
            formData.append(`files.${name}`, file, file.name);
          });
        }
      });

    formData.append('data', JSON.stringify(data));

    await fetch('/api/restaurants', {
      method: 'post',
      body: formData
    });
  });
</script>

您的输入数据必须包含在 data 键中,并且您需要 JSON.stringify 此对象。文件的键需要以 files 为前缀(例如,对于封面属性:files.cover)。

如果您要为可重复组件上传文件,则必须使用以下语法指定要将文件添加到的项目的从零开始的索引:files.my_component_name[the_index].attribute_name。例如,如果您放置了 3 个组件,并且文件用于第二个组件,则索引将为 1。

您必须在请求正文中发送 FormData。

模型定义

向模型(或另一个插件的模型)添加文件属性就像添加新关联一样。

在下面的第一个示例中,您将能够上传并将一个文件附加到头像属性。

./src/api/restaurant/content-types/restaurant/schema.json
json
{
  "attributes": {
    "pseudo": {
      "type": "string",
      "required": true
    },
    "email": {
      "type": "email",
      "required": true,
      "unique": true
    },
    "avatar": {
      "type": "media",
      "multiple": false
    }
  }
}

在我们的第二个例子中,您可以上传并附加多张图片到餐厅。

./src/api/restaurant/content-types/restaurant/schema.json
json
{
  "attributes": {
    "name": {
      "type": "string",
      "required": true
    },
    "covers": {
      "type": "media",
      "multiple": true
    }
  }
}

更新 fileInfo

更新应用程序中的文件。

接受以下参数:

  • fileInfo:要更新的文件信息。
js
import { FormData } from 'formdata-node'
import fetch from 'node-fetch'

const fileId = 50
const newFileData = {
  alternativeText: 'My new alternative text for this image!',
}

const form = new FormData()

form.append('fileInfo', JSON.stringify(newFileData))

const response = await fetch(`http://localhost:1337/api/upload?id=${fileId}`, {
  method: 'post',
  body: form,
})

从 API 控制器上传单个文件

从后端将文件添加到媒体库。

js
async create(ctx) {

  // ...

  const { body, files } = ctx.request;

  const file = files["files.uploadedFile"];

  const createdFiles = await strapi.plugins.upload.services.upload.upload({
    data: {
      fileInfo: {
        name: "Name",
        caption: "Caption",
        alternativeText: "Alternative Text",
      },
    },
    files: file,
  });

  // ...

},