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

背景

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

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

譬如:

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

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

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

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

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

  1. POST https://httpbin.org/post HTTP/1.1
  2. Host: httpbin.org
  3. Content-Length: 495
  4. Content-Type: multipart/form-data; boundary=---------------------------7db2d1bcc50e6e
  5. -----------------------------7db2d1bcc50e6e
  6. Content-Disposition: form-data; name="foo"
  7. bar
  8. -----------------------------7db2d1bcc50e6e
  9. Content-Disposition: form-data; name="upload1"; filename="/tmp/file.md"
  10. Content-Type: text/plain
  11. This is file1.
  12. -----------------------------7db2d1bcc50e6e
  13. Content-Disposition: form-data; name="upload2"; filename="/tmp/file2.md"
  14. Content-Type: text/plain
  15. This is file2, it's longer.
  16. -----------------------------7db2d1bcc50e6e--

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

旧模式

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

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

新模式

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

  1. const httpclient = require('urllib');
  2. async function run() {
  3. // 发起请求
  4. const url = 'https://httpbin.org/post';
  5. const result = await httpclient.request(url, {
  6. dataType: 'json',
  7. method: 'POST',
  8. // 设置普通的 headers
  9. data: {
  10. foo: 'bar',
  11. },
  12. // 单文件上传
  13. files: __filename,
  14. // 多文件上传
  15. // files: {
  16. // file1: __filename,
  17. // file2: fs.createReadStream(__filename),
  18. // file3: Buffer.from('mock file content'),
  19. // },
  20. });
  21. console.log(result.data.files);
  22. }
  23. run().catch(console.error);

在 Egg 中使用

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

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

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

  1. // app/controller/http.js
  2. class HttpController extends Controller {
  3. async upload() {
  4. const { ctx } = this;
  5. const result = await ctx.curl('https://httpbin.org/post', {
  6. method: 'POST',
  7. dataType: 'json',
  8. // 设置普通的 headers
  9. data: {
  10. foo: 'bar',
  11. },
  12. // 单文件上传
  13. files: __filename,
  14. // 多文件上传
  15. // files: {
  16. // file1: __filename,
  17. // file2: fs.createReadStream(__filename),
  18. // file3: Buffer.from('mock file content'),
  19. // },
  20. });
  21. ctx.body = result.data.files;
  22. // 响应最终会是类似以下的结果:
  23. // {
  24. // "file": "'use strict';\n\nconst For...."
  25. // }
  26. }
  27. }

相关资料

科普文: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. [LeetCode] 261. Graph Valid Tree 图是否是树

    Given n nodes labeled from 0 to n - 1 and a list of undirected edges (each edge is a pair of nodes), ...

  2. git删除远程.idea目录

    git删除远程.idea目录 1. 登录 Administrator@USER-20180708AB MINGW32 / (master) $ git config --global user.nam ...

  3. Python 获取文件类型后缀

    import os path='file.txt' file=os.path.splitext(path) filename,type=file print(filename) print(type)

  4. 如何在Linux中结合示例使用'cat'和'tac'命令

    上一篇我们讲到了cat的使用示例:https://www.cnblogs.com/WeiLian1024/p/11863057.html 本篇我们将继续延续Cat讲讲Tac 本文是我们讲讲Linux技 ...

  5. C语言实现简单的计算器(加、减、乘、除)

    利用运算符做为swich  case 语句条件,实现简单程序的编写;并且对输入的运算做判断,除数为零也需做判断; #include<stdio.h> int add(int a, int ...

  6. bootstrap table 列表增加输入框并保存输入的值不清除

    需求: 在bootstrap table上增加输入框,需要选择的时候把输入的值保存到 row 里面,传递给其他模块使用. 实现: columns: [{ ...., { field: 'myField ...

  7. java 正则和连接json

    前面已经写了不少关于C# 怎么使用正则,有兴趣,可以翻译成java代码. 以图片为例子: import java.util.regex.Matcher; import java.util.regex. ...

  8. ③ Python3.0 数字类型

    Python3 的六个标准数据类型中:不可变数据(3 个):Number(数字).String(字符串).Tuple(元组):可变数据(3 个):List(列表).Dictionary(字典).Set ...

  9. kubernetes第三章--创建harbor私有镜像库

  10. title 有背景边框自适应 mobile

    固定宽度,固定高度,来写背景的高度.这样就能居中.