这篇文章开头不是一个,不是两个,而是三个免责声明。 仔细读!
首先,如果您要将文件上传到OpenWhisk操作,则可以,但是文件大小不得超过一兆。 这虽然很小,但是请不要忘记可以使用第三方云存储提供商来提供文件。 (IBM提供了一个Cloud Object Storage服务,在这里很有用,而且Amazon S3显然也可以使用。)别忘了在尝试发布文件之前,您可以在JavaScript中检测文件的大小。
其次,虽然我能够获得一个解决方案,但我确实感觉这是OpenWhisk在平台级别可以更好地处理的事情。 我将详细介绍一些困难的部分以及我必须做的事情,但是正如我所说,我认为这是将来可以并且应该改进的地方。 如果发生这种情况,我会尽力尝试并返回这篇文章,但是……我已经老了。 我忘了东西。 因此,请记住这篇文章的日期。
第三,这是一个一般性的警告,然后是其他任何警告,尽管我爱邮差,但在我测试时它对我来说无法正常工作。 我将100%归咎于我,但是当我从Postman切换到“普通的旧HTML表单”进行测试时,我取得了很多进步。
好了,准备好了吗?
对于我的动作,我只想看到它正在处理包含文件的表单。 OpenWhisk将已经解析“常规”类型的FORM数据,您的文本字段等。 我对文件所做的操作不一定重要(我尝试了一些尝试只是为了确保它确实起作用),但是几乎所有内容都应该起作用。
您会认为这很容易。 有很多npm软件包,使处理文件上传变得容易。 我最喜欢的是强大的。 但是,它们都遭受OpenWhisk的一个核心问题-他们需要HttpRequest对象的实例。
使用Express时,您已经掌握了这些。但是在OpenWhisk下,所有这些操作都是在后台进行的。 您确实传递了100%(afaik)的请求数据,但是它本身并不是正确的HttpRequest对象。 我尝试伪造它,但是效果不佳。 (实际上,另一个项目使用的一种解决方案是使用SuperTest模拟对象。)
我在Twitter上提问时,得到了两个很好的提示-一个来自Wes Bos,另一个来自Cesidio Di Benedetto。 我的解决方案执行以下操作:
- 得到原始的身体。
- 使用字符串到流将该字符串转换为流。
- 将蒸汽传递给分手,这似乎是最底层,最简单的多部分表单解析器。
这一切都非常令人沮丧,似乎必须要有一些库才能让我向它传递一个巨大的多部分字符串(也许有!),但是我找不到“一枪打死”的解决方案。
好的-代码就是这样。 首先,该操作必须启用Web并启用原始主体。 就像这样:
wsk action update nameOfMyAction --web raw
现在获取代码。
var str = require('string-to-stream');
var multipart = require('parted').multipart;
var fs = require('fs');
function main(args) {
return new Promise((resolve, reject) => {
let decoded = new Buffer(args.__ow_body,'base64');
let newStream = str(decoded);
var options = {
limit: 30 * 1024,
diskLimit: 30 * 1024 * 1024
};
console.log('Making parser');
var parser = new multipart(args.__ow_headers["content-type"], options), parts = {};
parser.on('error', function(err) {
console.log('parser error', err);
});
parser.on('part', function(field, part) {
// temporary path or string
parts[field] = part;
});
parser.on('data', function() {
console.log('%d bytes written.', this.written);
});
parser.on('end', function() {
console.log(parts);
var file = fs.readFileSync(parts.file1);
var base64File = new Buffer(file).toString('base64');
resolve({
statusCode: 200,
headers: { 'Content-Type': 'image/png' },
body: base64File
});
});
newStream.pipe(parser);
});
}
exports.main = main;
我从获取原始身体开始。 记住,您必须告诉OpenWhisk,使其与我之前提到的注释一起使用。 然后,我使用字符串到流制作了一个伪流。 然后,我使用了parted-我几乎只是复制并粘贴了他们的样本。 最终结果是一个parts
对象,其中包含我所有的表单字段,其中文件是临时文件系统的路径。 总体而言,这很简单,但是我创建decoded
的那一行花了我一个小时尝试随机废话,直到正确为止。
基本上,就是这样。 分开完成后(请参见end
事件),我基本上将文件“回显”给用户。 我的代码假定一个名为file
的文件字段,并假定它是png。 但是,如果不这样做,将是微不足道的,但是对于演示而言,我只想要快速又脏的东西。
前端只是一个HTML表单:
<form
action="https://openwhisk.ng.bluemix.net/api/v1/web/rcamden@us.ibm.com_My%20Space/safeToDelete/filetest1"
method="post" enctype="multipart/form-data">
这是一个完全不需要的动画gif,可以将其显示出来。

您可以在此处找到此演示的源代码:https://github.com/cfjedimaster/Serverless-Examples/tree/master/file_upload
再说一遍–考虑一下整个示例,其中覆盖了一层“谨慎使用”,并撒上了“你在开玩笑吗”。 它奏效了,但希望以后能分享更好的解决方案。