zoukankan      html  css  js  c++  java
  • 科普文:Node.js 如何上传文件到后端服务【转】

    原文链接 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';
    
    const 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';
    
    const For...."
        // }
      }
    }

    相关资料

  • 相关阅读:
    CTO干点啥?
    [转] 持续集成与持续交付备忘录
    [转]概率基础和R语言
    程序自信
    [转]Neural Networks, Manifolds, and Topology
    ubuntu14 + nginx + php
    [转]http://makefiletutorial.com/
    REDIS key notification
    GO RPC
    xpcall 安全调用
  • 原文地址:https://www.cnblogs.com/richard1015/p/11100909.html
Copyright © 2011-2022 走看看