原文链接 https://www.yuque.com/egg/nodejs/httpclient-upload

背景

互联网时代,无数服务是基于 HTTP 协议进行通信的。

除了常见的 前端浏览器 -> Node 应用 外, Node 应用 -> 后端服务 也是一种非常常见的应用场景。

譬如:

  • 调用后端微服务,查询或更新数据。
  • 把日志上报给第三方服务。
  • 发送文件给后端服务。

Node.js 本身有提供了 http.request() 的能力,但它太底层了,因此社区有 requestsuperagent 等库。

我们在日常工作中也沉淀出了 urllib 这个基础库,可以使用它来非常便捷地完成任何 HTTP 请求。

request 目前已经放弃维护,详见 GitHub 置顶的 2 个 issue:

回到场景,『发送文件给后端服务』是其中一个非常典型的场景,对应于 RFC 1867 规范

POST https://httpbin.org/post HTTP/1.1
Host: httpbin.org
Content-Length: 495
Content-Type: multipart/form-data; boundary=---------------------------7db2d1bcc50e6e -----------------------------7db2d1bcc50e6e
Content-Disposition: form-data; name="foo" bar
-----------------------------7db2d1bcc50e6e
Content-Disposition: form-data; name="upload1"; filename="/tmp/file.md"
Content-Type: text/plain This is file1.
-----------------------------7db2d1bcc50e6e
Content-Disposition: form-data; name="upload2"; filename="/tmp/file2.md"
Content-Type: text/plain This is file2, it's longer.
-----------------------------7db2d1bcc50e6e--

然而,对于前端新手来说,有一定的学习门槛,因此,我们提供了一种简化的方式,来减轻新手上手成本。

旧模式

需要自行引入 formstream 这个模块来来帮助我们生成可以被 HttpClient 消费的 form 对象。

const FormStream = require('formstream');
const httpclient = require('urllib'); async function run() {
// 构造对应的 form stream
const form = new FormStream();
form.field('foo', 'bar'); // 设置普通的 headers
form.file('file', __filename); // 添加文件,上传当前文件本身用于测试
// form.file('file2', __filename); // 执行多次来添加多文件 // 发起请求
const url = 'https://httpbin.org/post';
const result = await httpclient.request(url, {
dataType: 'json',
method: 'POST', // 生成符合 multipart/form-data 要求的请求 headers
headers: form.headers(),
// 以 stream 模式提交
stream: form,
}); console.log(result.data.files);
// 响应最终会是类似以下的结果:
// {
// "file": "'use strict';\n\nconst For...."
// }
} run().catch(console.error);

新模式

开发者无需自行组装和引入额外模块,仅需提供 files 这个参数即可。

const httpclient = require('urllib');

async function run() {
// 发起请求
const url = 'https://httpbin.org/post';
const result = await httpclient.request(url, {
dataType: 'json',
method: 'POST', // 设置普通的 headers
data: {
foo: 'bar',
}, // 单文件上传
files: __filename, // 多文件上传
// files: {
// file1: __filename,
// file2: fs.createReadStream(__filename),
// file3: Buffer.from('mock file content'),
// },
}); console.log(result.data.files);
} run().catch(console.error);

在 Egg 中使用

Egg 基于 urllib 内置实现了一个 HttpClient,方便应用开发者便捷地发起 HTTP 请求。

注意:本文介绍的是 Node 应用 -> 后端服务 之间的文件上传。

如果你想了解的是 前端浏览器 -> Node 应用 之间的文件上传,请参考对应的文档

// app/controller/http.js
class HttpController extends Controller {
async upload() {
const { ctx } = this; const result = await ctx.curl('https://httpbin.org/post', {
method: 'POST',
dataType: 'json', // 设置普通的 headers
data: {
foo: 'bar',
}, // 单文件上传
files: __filename, // 多文件上传
// files: {
// file1: __filename,
// file2: fs.createReadStream(__filename),
// file3: Buffer.from('mock file content'),
// },
}); ctx.body = result.data.files;
// 响应最终会是类似以下的结果:
// {
// "file": "'use strict';\n\nconst For...."
// }
}
}

相关资料

科普文:Node.js 如何上传文件到后端服务【转】的更多相关文章

  1. node.js分片上传文件

    前端 : <html> <head> <title>分片上传文件</title> </head> <body> <div ...

  2. Node.js:上传文件,服务端如何获取文件上传进度

    内容概述 multer是常用的Express文件上传中间件.服务端如何获取文件上传的进度,是使用的过程中,很常见的一个问题.在SF上也有同学问了类似问题<nodejs multer有没有查看文件 ...

  3. Node.js——异步上传文件

    前台代码 submit() { var file = this.$refs.fileUpload.files[0]; var formData = new FormData(); formData.a ...

  4. vue.js异步上传文件前后端代码

    上传文件前端代码如下: <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type&q ...

  5. 利用ajaxfileupload.js异步上传文件

    1.引入ajaxfileupload.js 2.html代码 <input type="file" id="enclosure" name="e ...

  6. js获取上传文件内容(未完待续)

    js 获取上传文件的字节数及内容 <div> 上传文件 : <input type="file" name = "file" id = &qu ...

  7. Atitit.js获取上传文件全路径

    Atitit.js获取上传文件全路径 1. 默认的value只能获取文件名..安全原因.. 1 2. Firefox浏览器的读取 1 3. Html5 的file api 2 4. 解决方法::使用a ...

  8. js获取上传文件内容

    js 获取上传文件的字节数及内容 <div> 上传文件 : <input type="file" name = "file" id = &qu ...

  9. js能否上传文件夹

    文件夹上传:从前端到后端 文件上传是 Web 开发肯定会碰到的问题,而文件夹上传则更加难缠.网上关于文件夹上传的资料多集中在前端,缺少对于后端的关注,然后讲某个后端框架文件上传的文章又不会涉及文件夹. ...

随机推荐

  1. 关于LPC MUD的关键字及其它重要术语

    关于LPMUD的关键字及其它重要术语 前面的内容中对LPC语言和 lpmud 做了介绍,也完成了学习开发的准备工作,为了更好的学习,这里先对基本术语做一个说明. 关键字(Keywords):LPC语言 ...

  2. [LeetCode] 269. Alien Dictionary 外文字典

    There is a new alien language which uses the latin alphabet. However, the order among letters are un ...

  3. 【RSR】RSR如何配置BGP与BFD联动(动态路由)

    应用场景 企业租用运营商MSTP线路,配置BGP路由协议上网,由于企业本端出口路由器无法检测到运营商中间链路通信中断,导致路由收敛缓慢,无法快速的切换到其它备份线路,此时可以在路由器上启用BGP与BF ...

  4. Linux下zookeeper单机版详细安装

    Linux下zookeeper单机版详细安装 1.zookeeper简介 ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop ...

  5. Fastjson爆出重大漏洞,攻击者可使整个业务瘫痪

    360网络安全响应中心 https://cert.360.cn/warning/detail?id=82a509e4543433625d6fe4361b5802c9 报告编号:B6-2019-0905 ...

  6. Spring Cloud Alibaba学习笔记(24) - Spring Boot Actuator 监控数据可视化:Spring Boot Admin

    我们都知道,Spring Boot Actuator 提供监控数据是Json数据,在某种程度来说并不利于分析查看,那么如何将其进行可视化呢?我们有很多种选择,但是目前在这个领域,最流行的是Spring ...

  7. WPF 不要给 Window 类设置变换矩阵(分析篇):System.InvalidOperationException: 转换不可逆。

    原文:WPF 不要给 Window 类设置变换矩阵(分析篇):System.InvalidOperationException: 转换不可逆. 最近总是收到一个异常 "System.Inva ...

  8. 2.Vue 获取企业微信的Code并把Code发送的后台进行验证

    1 . 在企业微信配置请求的页面写入下面代码 mounted() { //获取微信请求的的Code let code = this.$route.query.code; if (code) { thi ...

  9. iOS - 动态库上架瘦身(去调虚拟机架构),不然验证会报错。

    eg: localhost:改造 M.emor.Y$ lipo WebRTC.framework/WebRTC -thin armv7 -output WebRTC_armv7localhost:改造 ...

  10. iOS 播放系统自带铃声

    播放声音代码例子 https://github.com/baitongtong/git-.git 给一个国外网址,苹果系统铃声以及自定义铃声免登陆免费下载:http://www.zedge.net/r ...