Discourse 文件上传的新时代

在过去的几个月中,您可能已经注意到许多与 Discourse 核心上传相关的提交。这是核心内部从我们的代码库替换jQuery 文件上传的使用的整体努力的一部分,作为从我们的代码库替换 jQuery 本身的使用的更广泛的整体努力的一部分。jQuery 文件上传器是一个非常古老的项目,几乎从一开始就成为 Discourse 核心的一部分。我想我在其他项目的整个职业生涯中也都使用过它。但是是时候让 Ol’ Reliable 退休了:

图片

我们已经用一个名为Uppy的库替换了 jQuery 文件上传(并且很快也会替换另一个库resumable.js)。这是一个更现代的上传库,可以通过插件轻松扩展,并且能够处理我们投入的所有不同工作流程。重要的是,这允许我们从 Discourse 客户端直接分段上传到 S3,而不必通过我们的 API 发送大文件。

编辑器现在将 Uppy 用于所有上传,整个应用程序中的许多其他地方都使用它(头像上传、个人资料背景上传等)。在接下来的几周内,最后的几个坚持将消失。对于大多数用户来说,这应该是一个很大程度上不可见的更改,但是插件和主题组件作者需要进行一些更改。

插件API

预处理器

所有上传预处理器现在都需要编写为Uppy 插件。这些插件编写起来非常简单,并使用简单的基于 Promise 的工作流程。在 Uppy 将文件上传到 S3 或/uploads.json 端点之前,上传预处理器可以修改文件或向其中添加元数据。我们已经在核心中有几个预处理器,您可以在编写自己的时用作参考:

通过api.addComposerUploadPreProcessor 使用插件 API注册 Composer 的上传预处理器:

github.com

discourse/discourse/blob/6662101208089def86ed18a81ac90d1c52670569/app/assets/javascripts/discourse/app/lib/plugin-api.js#L1041-L1072

/** * Registers a pre-processor for file uploads in the form * of an Uppy preprocessor plugin. * * See https://uppy.io/docs/writing-plugins/ for the Uppy * documentation, but other examples of preprocessors in core * can be found in UppyMediaOptimization and UppyChecksum. * * Useful for transforming to-be uploaded files client-side. * * Example: * * api.addComposerUploadPreProcessor(UppyMediaOptimization, ({ composerModel, composerElement, capabilities, isMobileDevice }) => { *   return { *     composerModel, *     composerElement, *     capabilities, *     isMobileDevice, *     someOption: true, *     someFn: () => {},

此文件已被截断。显示原件

上传处理程序

上传处理程序不是 作为 Uppy 插件编写的;他们仍然像往常一样工作,只是做了一个小改动。现在,当文件与注册到上传处理程序的扩展名匹配时,所有匹配的文件将立即发送 。以前一次只有一个文件会被发送到上传处理程序,而现在发送的是一个数组:

github.com

discourse/discourse/blob/6662101208089def86ed18a81ac90d1c52670569/app/assets/javascripts/discourse/app/lib/plugin-api.js#L1024-L1039

/** * Registers a function to handle uploads for specified file types. * The normal uploading functionality will be bypassed if function returns * a falsy value. * * Example: * * api.addComposerUploadHandler(["mp4", "mov"], (files, editor) => { *   files.forEach((file) => { *     console.log("Handling upload for", file.name); *   }); * }) */addComposerUploadHandler(extensions, method) {  addComposerUploadHandler(extensions, method);}

上传处理程序处理的文件不会在 Uppy 上传管道中进一步处理。预处理器在调用上传处理程序之前运行。

S3 分段直接上传

之前我提到我们使用 Uppy 还允许我们从 UI 直接分段上传到 S3。要启用此功能,您需要将enable_direct_s3_uploads 站点设置设置为true

如果您由我们托管,则相关的 S3 权限已应用于您的存储桶。但是,如果您是自托管,则必须在您的存储桶上设置多个权限和 CORS 规则才能使其正常工作。

对于 CORS 规则,您只需要s3:ensure_cors_rules 使用rake s3:ensure_cors_rules . 只要您为 Discourse 实例上的 S3 凭证设置的任何访问和密钥启用S3:GetBucketCorsS3:PutBucketCors 启用了权限,它就会将以下规则添加到您的存储桶中。

{
  "AllowedHeaders": [
    "Authorization",
    "Content-Disposition",
    "Content-Type"
  ],
  "AllowedMethods": [
    "GET",
    "HEAD",
    "PUT"
  ],
  "AllowedOrigins": [
    "*"
  ],
  "ExposeHeaders": [
    "ETag"
  ],
  "MaxAgeSeconds": 3000
}

对于权限,您需要为您在 Discourse 实例上为 S3 凭证设置的任何访问和密钥启用以下权限。

{
    "Sid": "YourSid",
    "Effect": "Allow",
    "Action": [
        "s3:PutObjectVersionAcl",
        "s3:PutObjectAcl",
        "s3:PutObject",
        "s3:GetObjectAcl",
        "s3:GetObject",
        "s3:DeleteObject",
        "s3:CreateMultipartUpload",
        "s3:CompleteMultipartUpload",
        "s3:AbortMultipartUpload"
    ],
    "Resource": [
        "YOUR_RESOURCE"
    ]
}

这是一个漫长的几个月的制作过程,我们还没有完成!当我们即将从 Discourse 核心中完全删除 jQuery 文件上传器和 resumable.js 时,我将在这个主题中发布。如果您对我在此处发布的内容有任何疑问,请告诉我!