科普文:Node.js 如何上传文件到后端服务【转】
原文链接 https://www.yuque.com/egg/nodejs/httpclient-upload
背景
互联网时代,无数服务是基于 HTTP 协议进行通信的。
除了常见的 前端浏览器 -> Node 应用 外, Node 应用 -> 后端服务 也是一种非常常见的应用场景。
譬如:
- 调用后端微服务,查询或更新数据。
 - 把日志上报给第三方服务。
 - 发送文件给后端服务。
 
Node.js 本身有提供了 http.request() 的能力,但它太底层了,因此社区有 request、superagent 等库。
我们在日常工作中也沉淀出了 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 应用 -> 后端服务之间的文件上传,如果你想了解的是前端浏览器 -> Node 应用之间的文件上传,请参考对应的文档。 - 相关文档:httpclient 。
 - 对应的 PR 实现:https://github.com/node-modules/urllib/pull/322
 
科普文:Node.js 如何上传文件到后端服务【转】的更多相关文章
- node.js分片上传文件
		
前端 : <html> <head> <title>分片上传文件</title> </head> <body> <div ...
 - Node.js:上传文件,服务端如何获取文件上传进度
		
内容概述 multer是常用的Express文件上传中间件.服务端如何获取文件上传的进度,是使用的过程中,很常见的一个问题.在SF上也有同学问了类似问题<nodejs multer有没有查看文件 ...
 - Node.js——异步上传文件
		
前台代码 submit() { var file = this.$refs.fileUpload.files[0]; var formData = new FormData(); formData.a ...
 - vue.js异步上传文件前后端代码
		
上传文件前端代码如下: <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type&q ...
 - 利用ajaxfileupload.js异步上传文件
		
1.引入ajaxfileupload.js 2.html代码 <input type="file" id="enclosure" name="e ...
 - js获取上传文件内容(未完待续)
		
js 获取上传文件的字节数及内容 <div> 上传文件 : <input type="file" name = "file" id = &qu ...
 - Atitit.js获取上传文件全路径
		
Atitit.js获取上传文件全路径 1. 默认的value只能获取文件名..安全原因.. 1 2. Firefox浏览器的读取 1 3. Html5 的file api 2 4. 解决方法::使用a ...
 - js获取上传文件内容
		
js 获取上传文件的字节数及内容 <div> 上传文件 : <input type="file" name = "file" id = &qu ...
 - js能否上传文件夹
		
文件夹上传:从前端到后端 文件上传是 Web 开发肯定会碰到的问题,而文件夹上传则更加难缠.网上关于文件夹上传的资料多集中在前端,缺少对于后端的关注,然后讲某个后端框架文件上传的文章又不会涉及文件夹. ...
 
随机推荐
- python中urllib的urlencode与urldecode
			
当url地址含有中文,或者参数有中文的时候,这个算是很正常了,但是把这样的url作为参数传递的时候(最常见的callback),需要把一些中文甚至'/'做一下编码转换. urlencode urlli ...
 - js的style.width取不到元素的宽度值
			
使用jquery的.width()方法获取一个元素的当前宽度,不管元素是否设置了宽度,css样式时内联 外联或者是内嵌,都可以使用 这个方法获取元素的宽度. 使用原生js style.width .w ...
 - [LeetCode] 409. Longest Palindrome 最长回文
			
Given a string which consists of lowercase or uppercase letters, find the length of the longest pali ...
 - mysql 5.7 sql_mode设置 坑
			
原文地址:https://blog.csdn.net/u012259256/article/details/56482218 1.查看sql_mode select @@sql_mode查询出来的值为 ...
 - 用js实现promise
			
/* 自定义promise 1. 执行MyPromise构造函数,要立即执行executor 2. promise实例对象,内部有三种状态 ...
 - [转帖]中兴GoldenDB数据库开始了第一轮中信银行核心业务系统迁移落地
			
中兴GoldenDB数据库开始了第一轮中信银行核心业务系统迁移落地 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https:// ...
 - STL源码剖析——序列式容器#1 Vector
			
在学完了Allocator.Iterator和Traits编程之后,我们终于可以进入STL的容器内部一探究竟了.STL的容器分为序列式容器和关联式容器,何为序列式容器呢?就是容器内的元素是可序的,但未 ...
 - 栈习题(1)-对于任意的无符号的的十进制数m,写出将其转换为十六进制整数的算法(正确输出即可)
			
/*对于任意的无符号的的十进制数m,写出将其转换为十六进制整数的算法(正确输出即可)*/ /* 算法思想:利用辗转取余法,每次都将余数存入栈中,直到被除数等0,退出循环. 输出栈里的内容即可 */ v ...
 - Connection to api@localhost failed. [08001] Could not create connection to d
			
pycharm 换成2019之后连接数据库用户名密码数据库名字都没错,就是连接不上去,网上百度一下,试试将URL后面拼接 ?useSSL=false&serverTimezone=UTC 发现 ...
 - visual studio code 命令行创建发布一个项目
			
安装vs core 打开按ctrl+~键打开终端 输入dir看看有什么文件,输入md Test 创建一个文件夹,选择文件后创建一个项目 输入dotnet可以查看信息 执行dotnet --help或者 ...