node.js 组件
在本系列的第一部分中,我们介绍了TransloadIt —一种文件处理服务,专门处理图像,视频和音频。 如果您还没有阅读它,我建议您立即阅读,因为它涵盖了很多背景概念,您需要阅读这些概念才能继续阅读本部分。
但是,有了足够的推理,背景和理论,我们来看一个实际的示例,说明如何使用该服务处理您自己的应用程序中的某些图像。
出于本教程的目的,我们将为任意应用程序实现用户个人资料照片功能。 我们将使用TransloadIt执行以下操作:
- 拦截文件上传,而不是将其上传到您的应用程序,而是上传到其服务器。
- 执行服务器端文件检查,以确保它满足某些条件,例如它是否确实是映像。
- 创建上载图像的许多不同派生形式(例如大小),例如各种尺寸的缩略图以及用户个人资料页面的“中”和“大”版本。
- 将所得衍生产品转移到Amazon S3存储桶。
- 在我们的应用程序中显示新上传图像的缩略图。
- 使用从TransloadIt返回的信息,让我们的应用程序知道在哪里可以找到生成的图像,以便我们可以在用户记录中存储对它们的引用。
第一步是构建一些包含汇编指令的模板。
模板入门
模板包含JSON格式的汇编指令。 启动您喜欢的文本编辑器,开始一些JSON:
{
}
……让我们深入。
筛选档案
首先,我们将添加一个步骤,该步骤利用/ file / filter机器人检查上传的文件的MIME类型,以确保它是图像。 将以下内容添加到您的空JSON文档中:
"steps":
"files": {
"robot": "/file/filter",
"accepts": [
[
"${file.mime}",
"regex",
"image"
]
],
"error_on_decline": true
},
让我们分解一下。
我们从密钥files
确定的步骤开始。 您可以随心所欲地对其进行命名,但是在大多数情况下, files
才有意义。
接下来,我们告诉TransloadIt使用/file/filter/
机械手,该机械手用于对传入文件进行一些检查。 在这种情况下,我们告诉它要接受什么。 我们要求它提取文件的MIME类型并在其上运行一个正则表达式( image
)。
在TransloadIt指令中,变量使用美元符号和大括号
${}
。 指定正则表达式时,只需要指定它的主体即可。
如果我们设置的测试失败,则error_on_decline
参数可确保引发错误,而不是继续进行下一步。
换句话说,我们告诉TransloadIt拒绝所有不是图像的文件。
添加调整大小步骤
现在,让我们再创建三个步骤,每个步骤都做同样的事情-创建传入图像的派生(即特定大小)。
我们可以随意调用这些步骤,因此我们将使用为派生类提供一些上下文的名称medium
, large
和thumbnail
。
让我们定义以下步骤的第一步:
"medium": {
"use": ":original",
"robot": "/image/resize",
"width": 300,
"height": 200,
"resize_strategy": "fit"
},
在这里,我们定义了一个名为medium
的步骤,该步骤利用了/image/resize
机械手。 这需要许多参数,其中许多是可选的,这些参数在此处记录 。
use
参数告诉它调整原始文件的大小。
在这种情况下,我们将提供所需的尺寸-300 x 200像素-并指定调整大小策略。 可用的调整大小策略记录在这里 ,但本质上fit
确保了图像被调整大小以适应指定的尺寸,同时保持高宽比。
![](https://i-blog.csdnimg.cn/blog_migrate/95a616c5d3dea98e2c2d529a42df6384.png)
免费学习PHP!
全面介绍PHP和MySQL,从而实现服务器端编程的飞跃。
原价$ 11.95 您的完全免费
large
步骤实际上是相同的:
"large": {
"use": ":original",
"robot": "/image/resize",
"width": 480,
"height": 320,
"resize_strategy": "fit"
},
然后thumbnail
步骤:
"thumbnail": {
"use": ":original",
"robot": "/image/resize",
"width": 80,
"height": 80,
"resize_strategy": "crop"
},
这次我们使用crop
策略来确保最终得到的图像是完美的正方形。
为了使过程更高效,没有理由不设置
use
参数来告诉TransloadIt将缩略图基于已处理的大中型版本。
在此阶段,我们确保正在处理图像,并且已将其大小调整了三倍,以创建三个单独的图像导数。 接下来,我们将告诉TransloadIt如何处理新创建的派生类。
出口
如前所述,Transloadit不会长时间存储我们的文件-托管不是服务的全部内容-因此我们需要将文件移到更永久的位置。
我们将使用/s3/store
文件导出机器人将文件上传到Amazon S3存储桶。
这是配置该步骤的方法:
"export": {
"use": [
"medium",
"large",
"thumbnail"
],
"robot": "/s3/store",
"path": "users/profiles/${fields.username}_${previous_step.name}.${file.ext}",
"key": "YOUR-S3-AUTH-KEY",
"secret": "YOUR-S3-AUTH-SECRET",
"bucket": "YOUR-BUCKET-NAME"
}
您需要用自己的S3凭据和存储桶名称替换。
这比我们之前的步骤稍微复杂一些,所以让我们分解一下。
use
参数告诉机器人对每个调整大小后的图像执行此步骤,从而在S3上为每次上传生成三个文件。 如您所见, medium
, large
和thumbnail
匹配我们前面三个步骤的标识符。
然后,我们指定密钥(S3的路径术语),用于使用path
配置值存储生成的文件。 此名称与存储桶的完全限定域名结合在一起,随后成为生成的派生图像的URI。
在上面的示例中,我们使用以下模式:
users/profiles/${fields.username}_${previous_step.name}.${file.ext}
这种模式首先在路径前面加上users/profiles/
,然后使用一个名为username
的隐藏表单字段的值,我们将在稍后定义它。 然后将其与定义上一步的键(即我们的派生名称)连接起来。 最后,它添加了原始文件的扩展名,可以通过${file.ext}
变量访问该扩展名。
那是一个很大的嘴,所以也许最好用一个例子来说明。 给定用户名bob
,此模式将产生以下三个路径:
users/profiles/bob_medium.jpg
users/profiles/bob_large.jpg
users/profiles/bob_thumbnail.jpg
通过砍切和更改可用的变量,您可以采用各种命名策略。 敌人的例子,请考虑以下模式:
users/profiles/${fields.username}${file.meta.width}x${file.meta.width}.${file.ext}
通过串联用户名,结果文件的宽度和高度以及最后文件的扩展名,可以动态构造文件名。 这将导致如下所示:
users/profiles/bob480x320.jpg
请注意,如果图像小于导数的目标尺寸,则这些值将反映最终图像,而不是配置的尺寸。
要简单地使用原始文件名:
${file.name}
为了确保唯一性,以下变量提供了唯一的32个字符的前缀:
${unique_prefix}
有关可用变量的完整列表,请参阅文档中有关汇编程序变量的部分 。
上载范本
将所有这些步骤放在一起,组成模板的组装说明如下所示:
{
"steps": {
"files": {
"robot": "/file/filter",
"accepts": [
[
"${file.mime}",
"regex",
"image"
]
],
"error_on_decline": true
},
"medium": {
"use": ":original",
"robot": "/image/resize",
"width": 300,
"height": 200,
"resize_strategy": "fit"
},
"large": {
"use": ":original",
"robot": "/image/resize",
"width": 480,
"height": 320,
"resize_strategy": "fit"
},
"thumbnail": {
"use": ":original",
"robot": "/image/resize",
"width": 80,
"height": 80,
"resize_strategy": "crop"
},
"export": {
"use": [
"medium",
"large",
"thumbnail"
],
"robot": "/s3/store",
"path": "users/profiles/${fields.username}_${previous_step.name}.${file.ext}",
"key": "YOUR-S3-AUTH-KEY",
"secret": "YOUR-S3-AUTH-SECRET",
"bucket": "YOUR-BUCKET-NAME"
}
}
}
在适当的位置输入您自己的S3凭据,然后我们准备将模板上传到TransloadIt。
在本教程随附的示例代码存储库中,您可以在名为
template.json
的文件中找到上述JSON。
如果您尚未使用TransloadIt创建帐户, 则现在需要这样做 。
您需要登录; 然后转到您的信息中心(我的帐户)。 在左侧边栏中的集成下,选择模板 。 然后,单击右上角的“ 新建”按钮。
系统会要求您提供一个名称来标识您的模板-像user_avatars
这样的东西就可以了。 然后,粘贴到上面的JSON(您还将在本文随附的存储库的根目录中找到该JSON)中-确保已用您自己的JSON替换了虚拟S3值,然后点击Save 。
如果您想使用其他存储机制,例如(S)FTP或Rackspace Cloud Files,则可以在此处找到相关文档-只需相应地修改最后一步即可。
您将被带回到主模板文件,并且您会注意到为新创建的模板分配了一个哈希作为唯一ID。 记下这一点,因为稍后将需要它。
完成之后,让我们看一下如何从应用程序中使用TransloadIt。
示例应用
您可以在Github上找到一个示例应用程序来伴随本教程。
为了运行它,您需要确保已安装以下先决条件:
- Node.js
- npm
- MongoDB
- 凉亭
Vagrant用户将在存储库中找到一个Vagrant
Vagrantfile
,以创建包含所有列出的依赖项的VM。
本质上,它是一个简单的Express应用程序。 为简洁起见,我们在这里不涉及很多内容:
- 它使用config模块将应用程序的配置保存在
.yaml
文件中。 - 它使用Mongoose和MongoDB来定义用户模型。
- 它使用Passport和Local策略来提供简单的身份验证机制。
- 它提供了中间件来安全地对密码进行哈希处理。
- 它包含一些简单的中间件,以将某些路由限制为仅通过身份验证的用户。
- 它使用Handlebars,以及handlebars-layouts包来处理模板。
首先,克隆应用程序,然后安装依赖项:
npm install
bower install
该应用程序中有几个元素值得简要介绍。
这是User
模型的架构定义:
var userSchema = mongoose.Schema({
username : { type: String, required: true, unique: true },
email : { type: String, required: true, unique: true },
password : { type: String, required: true },
avatar : { type: mongoose.Schema.Types.Mixed, required: false }
});
注意我们如何包含类型为Mixed
的avatar
字段。 这将使我们能够将化身指定为哈希,例如:
user.avatar = {
thumbnail : 'http://your.bucket.name.aws.amazon.com/user/profile/bob_thumbnail.jpg',
medium : 'http://your.bucket.name.aws.amazon.com/user/profile/bob_medium.jpg',
large : 'http://your.bucket.name.aws.amazon.com/user/profile/bob_large.jpg'
};
现在基本结构已经就绪,让我们看一下TransloadIt的jQuery插件。
jQuery插件
在客户端与TransloadIt集成的最简单方法是使用官方的jQuery插件 ,尽管还有其他替代方法,我们将在本文后面看到。
可通过以下URL获得该插件的最新版本:
https://assets.transloadit.com/js/jquery.transloadit2-latest.js
最小集成涉及以下步骤:
- 您将插件绑定到表单
- 插件“劫持”表单提交,直接将文件发送到Transloadit
- 插件等待,直到文件已上传并处理
- Transloadit返回带有结果的JSON对象,该对象还将包含新生成文件的URL
- 它会创建一个隐藏的textarea元素,其中包含来自Transloadit的JSON
- 表格已提交给您的申请
这是初始化插件,告诉它使用模板的非常简单的示例:
$(function() {
$('#upload-form').transloadit({
wait: true,
params: {
auth: {
key: 'YOUR-AUTH-KEY'
},
template_id: 'YOUR-TEMPLATE-ID'
}
});
});
但是,正如我们在上一部分中指出的那样,在客户端代码中公开身份验证凭据不是一个好主意。 相反,我们将使用签名。
签名
签名是使用身份验证令牌的一种更安全的选择,尽管它们需要一些服务器端的工作。
本质上,使用签名要求您不要对客户端应用程序发送一堆指令到TransloadIt,而是对指令进行编码,并使用HMAC算法和专用认证密钥对它们进行加密。 结果生成了一个临时令牌(即签名),该令牌仅限于特定的指令组合。 因为它是临时的,所以如果该令牌被破坏,那么它将很快变得无用。
您不必担心自己生成签名的来龙去脉,因为我们可以使用第三方库来处理该过程。 如果您使用的是Node.js,则官方SDK将为您处理。
要安装库:
npm install transloadit --save
您需要身份验证密钥和身份验证密钥,可以从TransloadIt网站上的“ API凭据”部分获得。 将它们放在config\default.yaml
的相关部分。
您需要通过将
RENAME_THIS_TO_default.yaml
重命名或复制到default.yaml
来创建默认配置文件。
现在,创建TransloaditClient
类的实例,并为其提供身份验证详细信息:
var TransloaditClient = require('transloadit');
var transloadit = new TransloaditClient({
authKey : config.transloadit.auth_key,
authSecret : config.transloadit.auth_secret
});
接下来,定义要执行的操作的参数。 可以采用一组汇编指令的形式:
var params = {
steps: {
// ...
}
};
或者,就我们而言,我们只需提供模板的ID:
var params = {
template_id: 'YOUR-TEMPLATE-ID'
};
要创建签名:
var sig = transloadit.calcSignature(params);
这将导致散列包含签名(各种访问令牌)以及调用服务所需的参数。 因此,我们的sig
对象将如下所示:
{
signature: "fec703ccbe36b942c90d17f64b71268ed4f5f512",
params: {
template_id: 'YOUR-TEMPLATE-ID',
auth: {
key: 'idfj0gfd9igj9dfjgifd8gfdj9gfdgf',
expires: '2015-06-25T10:05:35.502Z'
}
}
}
为了将其传递给我们的Handlebars模板,以便我们JavaScript可以利用它,我们需要创建一个非常简单的助手:
app.engine('.hbs', exphbs(
{
extname: '.hbs',
defaultLayout: 'default',
helpers : {
json : function(context) {
return JSON.stringify(context);
}
}
}
));
现在让我们一起来定义account
路由,其中将包括我们的头像上传表格:
// The account page
app.get('/account', ensureAuthenticated, function(req, res){
// Require the TransloadIt client
var TransloaditClient = require('transloadit');
// Create an instance of the client
var transloadit = new TransloaditClient({
authKey : config.transloadit.auth_key,
authSecret : config.transloadit.auth_secret
});
// Build the Transloadit parameters...
var params = {
template_id : config.transloadit.template_id
};
// ...and generate the signature
var sig = transloadit.calcSignature(params);
return res.render('account', {
user: req.user,
sig : sig
});
});
然后,在相应的模板( views/account.hbs
)中,让我们从一些非常简单HTML开始:
<h2>Hello, {{ user.username }}</h2>
{{# if user.avatar }}
<img src="{{ user.avatar.thumbnail }}" id="avatar">
{{else}}
<img src="/avatar.png" id="avatar">
{{/if}}
<form method="POST" action="/avatar" id="avatar-form">
<input type="file" name="image" id="avatar-upload">
<input type="hidden" name="username" value="{{user.username}}">
</form>
请注意,我们包括一个包含用户名的隐藏字段。 我们将根据请求将其发送到TransloadIt,以便可以在我们的模板中使用它。
现在添加JavaScript,首先使用我们的json
Handlebars帮助器进行一些变量初始化:
var sig = {{{ json sig }}};
现在,我们将TransloadIt插件绑定到上传表单:
$(function() {
$('#avatar-form').transloadit({
wait: true,
params: JSON.parse(sig.params),
signature: sig.signature,
fields: true,
triggerUploadOnFileSelection: true,
autoSubmit: false,
onSuccess: function(assembly) {
$('img#avatar').attr('src', assembly.results.thumbnail[0].url + '?' + (new Date()).getTime() );
var derivatives = {
thumbnail : assembly.results.thumbnail[0].url,
medium : assembly.results.medium[0].url,
large : assembly.results.large[0].url
};
$.ajax({
type: 'post',
url: '/avatar',
data: derivatives,
success: function(resp){
console.log(resp);
}
})
}
});
});
这比我们之前介绍的最小集成初始化要复杂得多,因此让我们一次来进行一下了解。
我们从sig
变量中获取参数和签名,该变量是在服务器上生成的,然后编码为JSON。 因为params
部分是嵌套的,所以我们使用JSON.parse()
将其转换回一个对象,然后TransloadIt将从中提取相关参数。
在插件初始化中, wait
设置为true
,这意味着我们要等到两个文件都已上传并且已对其进行处理。
使用程序集通知 (您可以在稍后的“高级用法”部分中进行了解)意味着您不必等待文件被处理,在这种情况下,您可以将
wait
设置为false
。
fields
设置为true
可以告诉插件我们在发送文件进行处理时希望包括其他信息; 在我们的例子中,这是一个名为username
的隐藏表单字段,我们使用经过身份验证的用户的username填充该字段。
一旦用户选择了文件,而不是提交表单时,使用triggerUploadOnFileSelection
将文件发送到Transloadit。 一旦结果从Transloadit返回时, autoSubmit
阻止它提交表单,因为我们将自己手动进行操作。
当数据从Transloadit返回时,将触发onSuccess
回调,这为我们提供了assembly
中数据的哈希值。
assembly
对象包含一个results
属性,该属性又包含我们每个“步骤”的属性。 这些包含文件对象数组。 由于我们仅上传一个文件,因此它们将是包含单个项目的数组。 每个文件对象都包含许多属性,包括原始文件名,元信息,Transloadit的唯一ID以及其他细节。 要查看全部信息,您可能希望将其注销到控制台中并进行查看。 但是,我们真正感兴趣的只是url
属性,其中包含S3上生成的图像的URL。
或者,您可能希望使用
ssl_url
属性,该属性与url
相同,但通过HTTPS。
我们只是通过对应的派生名称提取三个URL,然后创建这三个派生及其对应URL的哈希。
为了向用户提供视觉反馈,我们还获取了缩略图的URL并修改页面上的头像以显示新上传的图像。
最后,我们使用Ajax将数据以静默方式发布回我们的应用程序。
这是捕获该数据的avatar
路线:
// Ajax callback for setting the avatar
app.post('/avatar', ensureAuthenticated, function(req, res){
req.user.avatar = req.body
req.user.save(function(err) {
if(err) {
return res.send('error');
}
return res.send('ok');
});
});
在生产中,您可能需要对此进行清理和验证。
如您所见,我们获取派生图像及其URL的哈希,从req.user
获取当前经过身份验证的用户,将avatar
属性设置为提供的哈希,然后更新用户模型。
这只是一种可能的方法。 为了获得更快的反馈,您可能希望使用插件的onResult
回调在缩略图生成后立即获取它,而不是等待所有三个派生类。 与其使用客户端代码中的Ajax调用来通知服务器,不如选择使用Assembly通知功能,该功能提供了在后台运行程序集的其他好处,而不是在客户端上阻止执行。 请查阅插件文档以获取所有选项。
到此结束我们的基本应用。 别忘了,所有源(包括身份验证机制)都在Github上结束了 。
高级用法
在总结之前,让我们简单地看一下TransloadIt的两个更高级的方面。
其他客户端选项
您不必使用提供的jQuery插件。 在文档的“ 社区项目”部分中,您可以找到许多替代方法,包括Bootstrap插件, drag n'drop插件, Angular插件或对简单的旧XHR的支持。
您可能需要更详细地了解XHR。 这是一个简单的解决方案,提供了很大的灵活性,同时要求您提供自己的反馈(例如某种上传指示器)。 还值得注意的是,一旦上传了文件,它将尝试通过以1000ms的间隔轮询服务器来确定何时完成了程序集。
通知事项
当文件准备好时,您可以使用通知来ping您的应用程序,而不必让用户等待处理他们的上载。 使用这种方法,用户只需等到上传完成即可。
从消费者的角度来看,通知很容易实现; 只需在您的汇编指令中包含notify_url
即可,例如:
{
auth : { ... },
steps : { ... },
notify_url : "http://example.com/webhooks/incoming/transloadit"
}
当您的URL被Transloadit ping通时,提供的JSON将包含一个signature
字段,您可以使用该字段来验证通知确实来自他们。 只需使用您的身份验证密钥对签名进行解码即可。
在开发过程中,您可能希望利用此代理软件包来测试程序集通知,或使用隧道服务(例如ngrok) 。
摘要
在这个由两部分组成的系列文章中,我们对文件处理服务TransloadIt进行了全面介绍。
在第一部分中,我们研究了一些优点和缺点,然后研究了关键概念。
这一部分,我们动手了,并使用jQuery,Node.js和Express构建了一个简单的用户头像组件。
您不仅限于jQuery,而且确实可以自由使用原始JavaScript解决方案或您喜欢的框架。 您甚至不需要在客户端应用程序中使用它,而在服务器端技术方面,您可以选择很多。 不过,希望您现在对如何将其用于图像处理有所了解。
您在项目中使用TransloadIt吗? 您知道更好的服务吗? 在评论中让我知道。
翻译自: https://www.sitepoint.com/user-avatar-component-node-js-transloadit/
node.js 组件