如何在函数计算中使用 Node.js 处理 multipart 文件上传请求-阿里云开发者社区

开发者社区> rocaltair> 正文

如何在函数计算中使用 Node.js 处理 multipart 文件上传请求

简介: web 开发中我们经常会允许用户通过 HTTP POST 请求上传文档到服务器,本文将介绍在函数计算中基于 node.js 使用 multipart form-data 来实现文件上传服务。
+关注继续查看

前言

web 开发中我们经常会允许用户通过 HTTP POST 请求上传文档到服务器,如何使用函数计算来做文件上传服务呢?下面我们使用 nodejs 来实现一个文件上传的案例:

我们知道浏览器中上传文档通常会使用 multipart form-data 来多文件同时上传文件。

例如,我们可以使用curl来做这个测试模拟上传两个文件: test.txtindex.js

curl -v --request POST --header "Content-Type:multipart/form-data" --form upload=@"test.txt" --form upload=@"index.js" https://example.com/upload/

格式分析

为了实现这个上传服务,我们先来了解一下 multipart 的 HTTP header 及 body 格式:

为了简单起见,我们使用一个文件内容为 111111\n 的文本文件 test.txt
通过上述指令,我们可以看到 request 的 header 部分,会多出一个类似下述的 header:

Content-Type:multipart/form-data; boundary=------------------------7b433b8e13cbec1c

而 POST body 则大致如下:

"--------------------------7b433b8e13cbec1c\r\nContent-Disposition: form-data; name=\"upload\"; filename=\"test.txt\"\r\nContent-Type: text/plain\r\n\r\n111111\n\r\n--------------------------7b433b8e13cbec1c--\r\n"

我们可以认为 body 被分成了多个片,每个片使用 header 中的 boundary 来做前后分隔,中间的内容则包含了这个分片的各种属性。

实现

安装第三方库

接下来,我们使用一个三方 parser 库 parse-multipart 来解析 POST body 的数据。

npm install parse-multipart

函数实现示例

我们在代码目录新增 index.js 粘贴以下内容:

// curl -v --request POST --header "Content-Type:multipart/form-data" --form upload=@"test.txt" https://<your-endpoint>/2016-08-15/proxy/test_service/file-upload/
var getRawBody = require('raw-body');

// see https://www.npmjs.com/package/parse-multipart
// npm install parse-multipart
var multipart = require('parse-multipart');

// regexp to parse boundary from HTTP header
var RE_BOUNDARY = /^multipart\/.+?(?:; boundary=(?:(?:"(.+)")|(?:([^\s]+))))$/i

module.exports.handler = function(req, resp, context) {
    console.log('file upload');

    var params = {
        path: req.path,
        queries: req.queries,
        headers: req.headers,
        method : req.method,
        requestURI : req.url,
        clientIP : req.clientIP,
    }
    getRawBody(req, function(err, body) {
        for (var key in req.queries) {
          var value = req.queries[key];
          resp.setHeader(key, value);
        }
        params.body = body.toString();
        var m = RE_BOUNDARY.exec(req.headers['content-type'])
        var boundary = m[1] || m[2]
        params.boundary = boundary
        var parts = multipart.Parse(body, boundary);
        params.parts = parts
        resp.send(JSON.stringify(params, null, '    '));
    });
}

创建函数后,我们可以为这个函数创建 HTTP trigger,并为选择 POST 作为可接受 HTTP Method。

测试

创建完成后,我们可以使用上面的 curl 命令来做测试:

curl -v --request POST --header "Content-Type:multipart/form-data" --form upload=@"test.txt" https://<endpoint>/2016-08-15/proxy/test_service/file-upload/

测试结果大致如下:

* TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
* Server certificate: *.fc.aliyuncs.com
* Server certificate: GlobalSign Organization Validation CA - SHA256 - G2
* Server certificate: GlobalSign Root CA
> POST /2016-08-15/proxy/test_service/file-upload/ HTTP/1.1
> Host: ************.cn-shanghai.fc.aliyuncs.com
> User-Agent: curl/7.54.0
> Accept: */*
> Content-Length: 195
> Expect: 100-continue
> Content-Type:multipart/form-data; boundary=------------------------7b433b8e13cbec1c
>
< HTTP/1.1 100 Continue
< HTTP/1.1 200 OK
< Access-Control-Expose-Headers: Date,x-fc-request-id,x-fc-error-type,x-fc-code-checksum,x-fc-invocation-duration,x-fc-max-memory-usage,x-fc-log-result,x-fc-invocation-code-version
< Content-Disposition: attachment
< Content-Length: 1089
< Content-Type: application/octet-stream
< X-Fc-Code-Checksum: 8133380019009032134
< X-Fc-Invocation-Duration: 4
< X-Fc-Invocation-Service-Version: LATEST
< X-Fc-Max-Memory-Usage: 17.31
< X-Fc-Request-Id: b227b724-b14b-6413-22be-c868b395c732
< Date: Tue, 04 Jun 2019 03:41:04 GMT
<
{
    "path": "/",
    "queries": {},
    "headers": {
        "accept": "*/*",
        "content-length": "195",
        "content-type": "multipart/form-data; boundary=------------------------7b433b8e13cbec1c",
        "expect": "100-continue",
        "user-agent": "curl/7.54.0"
    },
    "method": "POST",
    "requestURI": "/2016-08-15/proxy/test_service/file-upload/",
    "clientIP": "123.123.123.123",
    "body": "--------------------------7b433b8e13cbec1c\r\nContent-Disposition: form-data; name=\"upload\"; filename=\"test.txt\"\r\nContent-Type: text/plain\r\n\r\n111111\n\r\n--------------------------7b433b8e13cbec1c--\r\n",
    "boundary": "------------------------7b433b8e13cbec1c",
    "parts": [
        {
            "filename": "test.txt",
            "type": "text/plain",
            "data": {
                "type": "Buffer",
                "data": [
                    49,
                    49,
                    49,
                    49,
                    49,
                    49,
                    10
                ]
            }
        }
    ]
}

我们可以看到 parts 数组中的数据,其中 data 为一个 Buffer 字节数组[49, 49, 49, 49, 49, 49, 10],转成 string"111111\n"

使用限制

由于目前函数计算对于调用请求有最多 6MB 的大小限制,如果上传需要处理大文件,请先上传到 OSS bucket,然后再通过函数计算来处理相关请求。

更多参考

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
使用 Node.js Express 的最佳实践
使用 Node.js Express 的最佳实践
9 0
使用node.js获取图片的base64编码
把百度的logo保存到桌面进行测试,得到的编码为: R0lGODlhdQAmAKIAAOYyL+rU4llg6Jmd8e92dCky4eEGAv///yH5BAAAAAAALAAAAAB1ACYAAAP/eLrc/jC2IEoZMATJu/9gyFVWIUyksIls677LUJbrEcxW...
650 0
node.js获取图片文件的真实类型
遇到一个需求:假定有一个图片文件,真实的类型为jpg,而有人偷懒把jpg直接复制一张,存为同名的png文件,这样在as3读取文件时不会遇到问题,但手机c++在读取文件时却遇到问题了 - -!   现在就需要写一个程序,遍历所有文件夹下的文件,查找文件格式“不正常”的文件。
1217 0
SpringBoot-13-插曲之Node文件重命名+自动生成json对象
遇到的问题:图片太多,使用起来挺麻烦 [1]有很多图片放服务器里,怎么能更好的管理,更方便拿到图片呢? [2]想用json 以一个对象数组的形式保存这些图片:以[{img:"图片名"},{img:"图片名"}....]形式 [3]虽说想法是很好,但不可能一条一条自己写吧,好歹咱也是21世纪敲代码的人。
831 0
Spring Boot四:配置文件详解properties
一.配置随机数,使用随机数 在application.properties文件添加配置信息 #32位随机数 woniu.secret=${random.value} #随机整数 woniu.number=${random.
1763 0
如何在函数计算中使用结构化的用户日志
目前函数计算默认会将用户的标准输出写入到用户指定的 logstore ,如果使用了 `logger.log()` `console.log()` 这类函数还会带上时间戳及requestID。 通常情况下,对于普通用户来说这已经可以做一些问题调查和调试了。 但在很多情况下,我们可能需要做自定义的特定字段的查询,例如比较数字大小,比较字符串长度,做柱状图、饼图,曲线图等等。本文会介绍如何在函数
1175 0
nodejs如何储存一个GBK编码的文件
思路:utf-8 -> decode(to buffer) -> convert to gbk(buffer also) -> write buffer to file. var fs = require('fs'); var iconv = require('iconv-lite'); // 这里是utf8 var str = '坑爹啊,都是国际项目了,编码居然还用gbk'; console.
870 0
秘籍:使用函数计算珍藏你喜爱的文章
使用函数计算珍藏你喜爱的文章 1. 背景 对于喜欢阅读博客的程序员来说,是不是常常堆满 tab 标签,密密麻麻的连标题都看不清?不舍得关掉,却又抽不出来时间阅读?又或者阅读过了,想收藏起来供日后查阅? 对这些文章来说,onenote、印象笔记等笔记类软件着实不是一个好的去处。
1841 0
+关注
rocaltair
阿里云函数计算专家,擅长网络与数据通信领域。
8
文章
0
问答
来源圈子
更多
专注Serverless、微服务、函数计算等
+ 订阅
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载