logo

Extra Block Types (EBT) - New Layout Builder experience❗

Extra Block Types (EBT) - styled, customizable block types: Slideshows, Tabs, Cards, Accordions and many others. Built-in settings for background, DOM Box, javascript plugins. Experience the future of layout building today.

Demo EBT modules Download EBT modules

❗Extra Paragraph Types (EPT) - New Paragraphs experience

Extra Paragraph Types (EPT) - analogical paragraph based set of modules.

Demo EPT modules Download EPT modules

Scroll
04/09/2025, by Ivan

现在已支持上传文件,更多信息请参阅发行说明:https://www.drupal.org/node/3024331

下列两张图片展示了如何使用 Postman 通过 JSON:API 测试文件上传

Json API 文件头
Postman 中的 Json:API 请求头。

使用 Curl 上传用户头像示例

这里假设你已完成身份验证,并在其他请求中获取了 CSRF 令牌。

curl -s -X POST -b cookie.txt \
  --header "Accept: application/vnd.api+json" \
  --header "Content-Type: application/octet-stream" \
  --header "X-CSRF-Token: $TOKEN" \
  --header 'Content-Disposition: file; filename="test.jpg"' \
  --data-binary "@test.jpg" \
  http://localhost/jsonapi/user/user/$UUID/user_picture

在使用 axios(或其他 HTTP 客户端库)与 Node.js 时的提示:

你可能会发现,待上传的图片数据是 Buffer 格式。例如:

<Buffer ff d8 ff e0 00 10 4a 46 49 46 00 01 01 00 00 01 00 01 00 00 ff fe 00 3e 43 52 45 41 54 4f 52 3a 20 67 64 2d 6a 70 65 67 20 76 31 2e 30 20 28 75 73 69 ... 582549 more bytes>

虽然从技术上讲,这是二进制图像数据的 Buffer 对象表示,但如果直接把它作为数据参数通过你常用的 HTTP 客户端库(如 axios)发送到 Drupal,会导致生成不正确的文件。文件虽然会存在,响应也可能成功,但图片很可能只是一块黑底上的白色方块。

你需要使用 Node.js 的 Buffer 类将其转换为真正的二进制 Buffer 输出。具体来说,需要使用 from 方法。

例如:

假设我们使用 AWS S3 SDK 获取了一个文件对象,并取到了该文件对象的 Body。这个 Body 含有如上所示的 Buffer 数据。我们把 Body 数据放入一个变量中,使用 Buffer 类将其转换为正确的格式,然后使用 axios 将其发送到 Drupal 的 JSON:API 端点(注意:以下代码片段只展示关键部分而非完整处理器;实际项目中通常会拆分到一些辅助库中以保持 DRY)。关键一行是 data: Buffer.from(buffer, "binary")

const buffer = storedFile.Body; // 包含上文所示的 buffer 数据。

const drupalData = await axios({
  method: "post",
  url: url, // 你站点上的 /jsonapi/media/image/field_media_image/ 路径。
  auth: {
  	username: xxx
  	password: xxx
  },
  headers: {
    'Accept': 'application/vnd.api+json',
    'Content-Type': 'application/octet-stream',
    'X-CSRF-Token': token, // 需要先从 Drupal 的 /session/token 获取!
    'Content-Disposition': 'file; filename="' + filename + '"',
  },
  data: Buffer.from(buffer, "binary"),

});

console.log(drupalData); // 新创建文件的 uuid 位于 drupalData.data.id 中

如果你在使用 Node.js 的 AWS Lambda 函数并从 S3 拉取文件后上传至 Drupal,这种做法尤其有用。