在过去的几个月中,您可能已经注意到许多与 Discourse 核心上传相关的提交。这是核心内部从我们的代码库替换jQuery 文件上传的使用的整体努力的一部分,作为从我们的代码库替换 jQuery 本身的使用的更广泛的整体努力的一部分。jQuery 文件上传器是一个非常古老的项目,几乎从一开始就成为 Discourse 核心的一部分。我想我在其他项目的整个职业生涯中也都使用过它。但是是时候让 Ol’ Reliable 退休了:
我们已经用一个名为Uppy的库替换了 jQuery 文件上传(并且很快也会替换另一个库resumable.js)。这是一个更现代的上传库,可以通过插件轻松扩展,并且能够处理我们投入的所有不同工作流程。重要的是,这允许我们从 Discourse 客户端直接分段上传到 S3,而不必通过我们的 API 发送大文件。
编辑器现在将 Uppy 用于所有上传,整个应用程序中的许多其他地方都使用它(头像上传、个人资料背景上传等)。在接下来的几周内,最后的几个坚持将消失。对于大多数用户来说,这应该是一个很大程度上不可见的更改,但是插件和主题组件作者需要进行一些更改。
插件API
预处理器
所有上传预处理器现在都需要编写为Uppy 插件。这些插件编写起来非常简单,并使用简单的基于 Promise 的工作流程。在 Uppy 将文件上传到 S3 或/uploads.json
端点之前,上传预处理器可以修改文件或向其中添加元数据。我们已经在核心中有几个预处理器,您可以在编写自己的时用作参考:
- discourse/uppy-checksum-plugin.js at 6662101208089def86ed18a81ac90d1c52670569·discourse/discourse·GitHub
- discourse/uppy-media-optimization-plugin.js at 6662101208089def86ed18a81ac90d1c52670569·discourse/discourse·GitHub
通过api.addComposerUploadPreProcessor
使用插件 API注册 Composer 的上传预处理器:
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 插件编写的;他们仍然像往常一样工作,只是做了一个小改动。现在,当文件与注册到上传处理程序的扩展名匹配时,所有匹配的文件将立即发送 。以前一次只有一个文件会被发送到上传处理程序,而现在发送的是一个数组:
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:GetBucketCors
并S3: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 时,我将在这个主题中发布。如果您对我在此处发布的内容有任何疑问,请告诉我!