无中转上传

未匹配的标注

无中转上传允许你将传入的多部分流流式传输到 Amazon S3 或 Cloudinary 等云服务,而无需在你的服务器上处理它们。流程如下所示:

  • 用户上传文件。
  • 请求到达你的服务器。
  • 你无需解析请求并从中读取数据,而是将流传输到外部云服务。

由于是直接通过管道传输流,因此你的 AdonisJS 应用程序不必分配任何额外的内存或 CPU 计算来解析和保存磁盘上的数据。

什么时候不使用无中转上传?

就像你将在本指南后面部分看到的那样,直接文件上传很复杂,需要你直接处理流。

如果你的应用程序不处理大文件上传,我们建议使用 标准文件上传。请记住,有时编写更简单的代码甚至会获得一些性能提升。

用法

第一步是禁用 config/bodyparser.ts 文件中自动处理。禁用自动处理后,bodyparser 中间件会将多部分流转发到你的控制器,以便您可以手动处理它。

你可以通过将 autoProcess 属性设置为 false 来禁用整个应用程序的自动处理。

multipart: {
  autoProcess: false
}

你也可以通过将它们的路由匹配添加到 processManually 数组来对特定的路由禁用。

processManually: ['/drive']

处理多部分流

你可以按如下方式处理控制器内部的多部分流:

import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'

export default class DriveController {
  public async store({ request }: HttpContextContract) {
    request.multipart.onFile('input_field_name', {}, (part) => {
      someSdk.uploadStream(part)
    })

    await request.multipart.process()
  }
}

-request.multipart.process() 最先处理多部分流。
-request.multipart.onFile 方法允许你通过定义回调来处理给定文件输入的流。

  • 回调方法接收流实例 (part) 作为第一个参数,可以将此流写入你想要的任何地方。

获取处理后的流文件

一旦处理给定文件的流得到(成功或有错误)的结果,就可以使用 request.file 方法进行访问。例如:

request.multipart.onFile('input_field_name', {}, (part) => {
  someSdk.uploadStream(part)
})

await request.multipart.process()

const file = request.input('input_field_name')
if (file.hasErrors) {
  return file.errors
}

验证流

你还可以在流被写入时,对流中的每个块 (chunk) 进行验证,这需要你将每个块作为第二个参数传递给 onFile 回调。

request.multipart.onFile(
  'input_field_name',
  {
    extnames: ['pdf', 'jpg', 'png', 'doc', 'xls'],
    size: '200mb',  
  },
  (part, reportChunk) => {
    part.pause()
    part.on('data', reportChunk)
    someSdk.uploadStream(part)
  })
  • 首先,你必须为 extnamesize 定义验证规则。
  • 接下来,使用 reportChunk 方法并将每个块报告给内部辅助函数。
    -reportChunk 方法将在流传输时监控流,如果任何验证规则未满足,则会发出错误。
  • 一旦可读流上的 reportChunk 方法发出错误,可写流(你的 SDK)将/应该中止上传。

你注意到 part.pause 语句了吗?

在定义part.on('data')事件侦听器之前,你必须 暂停流。否则,流将在你的 SDK 准备好使用它之前开始传输数据。

错误处理

onFile 回调中发生的任何错误都会添加到文件实例中,你可以按如下方式访问它们。

request.multipart.onFile('input_field_name', {}, (part) => {
  throw new Error('blow up the stream')
})

await request.multipart.process()

const file = request.input('input_field_name')
console.log(file.errors) // 将包含流产生的所有错误

将元数据附加到处理后的流

你可以将元数据附加到已处理的流文件,这样将从 onFile 回调返回一个对象。例如,它可以是保存上传到云服务的文件的 URL 的对象。

request.multipart.onFile('input_field_name', {}, (part, reportChunk) => {
  part.pause()
  part.on('data', reportChunk)

  const url = await someSdk.uploadStream(part)
  return { url }
})

url 将在 file.meta 属性中可用。

await request.multipart.process()

const file = request.input('input_field_name')
console.log(file.meta) // { url: '...' }

注意事项

直接使用流时,你无法在处理整个流之前访问表单输入字段。这是因为表单字段和文件都是单个流的一部分,因此它们仅在处理流时可用。

注意:流处理期间表单域可能不可用

request.multipart.onFile('input_field_name', {}, (part) => {
  // 可用与否取决于字段在流中的位置
  request.input('some_field')
})

await request.multipart.process()

注意:可以流处理完毕后访问表单域

request.multipart.onFile('input_field_name', {}, (part) => {
})

await request.multipart.process()

// 处理方法后进行访问
request.input('some_field')

它与 AWS 直接上传有何不同?

AWS 允许直接从浏览器上传文件, 甚至不需要先到达你的服务器。

AdonisJS 直接上传是 AWS 直接上传的替代方法,但这两种方法都有其优点和缺点,如下所示。

AWS 直接上传

  • 直接从浏览器处理。
  • 需要额外的 HTTP 请求来生成身份验证签名。
  • 使用客户端 file.type 属性来检测文件内容类型。这很容易被欺骗。
  • 需要桶策略来验证文件类型和大小。
  • 文件上传通常更快,并且不需要在你的服务器上进行计算。

AdonisJS 直接上传

  • 从服务器处理。
  • 使用文件 magic number 来检测服务器上文件的内容类型。
  • 使用标准的服务器端验证。
  • 即使文件是直接流式传输的,你的服务器仍然必须接受请求。

本文章首发在 LearnKu.com 网站上。

本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://learnku.com/docs/adonisjs/5.x/ht...

译文地址:https://learnku.com/docs/adonisjs/5.x/ht...

上一篇 下一篇
贡献者:1
讨论数量: 0
发起讨论 查看所有版本


暂无话题~