V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
az09py
V2EX  ›  Node.js

node 中间层转发文件上传是否必须将文件存在本地呢

  •  
  •   az09py · 2019-01-24 11:50:12 +08:00 · 5083 次点击
    这是一个创建于 2129 天前的主题,其中的信息可能已经有所发展或是发生改变。

    先通过 formidable 解析文件,会把文件存到本地 然后通过 request.post 上传文件,这里必须文件必须通过 form.append (‘ file ’,fs.createReadStream(file.path))进行处理 这样就会在服务器上创建文件

    11 条回复    2022-10-22 13:30:19 +08:00
    libook
        1
    libook  
       2019-01-24 14:10:06 +08:00
    不需要吧,用 Stream,先建立客户端发来的请求的读 Stream,然后再建立转发到目标服务的写 Stream,然后两边管道接在一起。
    hcymk2
        2
    hcymk2  
       2019-01-24 14:11:43 +08:00
    pipe。
    doublleft
        3
    doublleft  
       2019-01-24 14:55:25 +08:00
    不用,可以 form.buffer
    az09py
        4
    az09py  
    OP
       2019-01-24 15:54:28 +08:00
    @libook 直接不需要 formidable 解析成 File 了么
    az09py
        5
    az09py  
    OP
       2019-01-24 15:56:12 +08:00
    @hcymk2 可以大致讲讲思路吗
    libook
        6
    libook  
       2019-01-24 16:30:12 +08:00
    看你想做哪些事情了,如果什么事情都不做,直接把上游发来的文件传递给下游,可以直接把 Stream 传递过去。

    ```
    http.createServer(function(req, res) {
    //这里的 req 是个 Stream
    const options = {
    hostname: 'http://你的上传服务器地址',
    port: 80,
    path: '/upload',
    method: 'POST',
    headers: {
    //这里写一些必要的头
    }
    };

    /**
    * 这个 uploadReq 也是个 Stream
    */
    const uploadReq = http.request(options, (res) => {
    //这里处理上传服务器的 response
    });

    req.pipe(uploadReq);//关键点,把上游发来的 Stream 直接管道接到下游上传服务器的 Stream 上


    }).listen(8080);
    ```

    上面是个示范,不是一个可执行的代码,只是提供一个思路。
    lps
        7
    lps  
       2019-01-25 14:23:35 +08:00
    可以参考 eggjs 的文件上传,不需要保存临时文件,直接通过 stream 转发到 OSS 存储
    dtlqwjj
        8
    dtlqwjj  
       2019-02-15 18:20:13 +08:00
    @doublleft file.buffer,怎么添加到 formdata,是 xx.append('file', file.buffer)吗?
    chogath
        9
    chogath  
       2020-09-01 16:40:50 +08:00
    node 中间层转发文件上传 可以使用 代理模式

    import { createProxyServer } from 'http-proxy';

    const proxy = createProxyServer({});

    const target = '< 需要转发的 url >'

    const result = await new Promise((resolve, rej) => {
    proxy.web(
    req,
    res,
    { target, ignorePath: true },
    (err: Error) => { if (err) rej(err.message); },
    );
    });
    keji
        10
    keji  
       2021-08-27 09:01:44 +08:00
    目前已解决,分享下我的方案,完整代码如下:

    const express = require("express");
    const multer = require("multer");
    const upload = multer();
    const app = express();
    app.post("/photos/upload", upload.array("files"), function (req, res, next) {
    //这里我默认取了数组的第一个数据,大家根据实际的情况进行组合数据
    const { originalname, mimetype, buffer } = req.files[0];
    request.post(
    {
    url: "后端服务器地址",
    headers: {
    //这里写一些必要的头
    },
    formData: {
    //注意,这里一定要按这样的格式写,因为如果不这样写的话
    //其中的 filename 字段会丢失 /Content-Type 的类型跟实际传过来不一致的,所以最好自己提前设置好
    //比如正确的是这样的(下面两行)
    //Content-Disposition: form-data; name="file"; filename="xxx"
    //Content-Type: image/jpeg
    //这个 bug 困扰我好久了,最后是通过抓包工具分析出来的(太菜了)
    file: {
    value: buffer,
    options: {
    filename: originalname,
    contentType: mimetype,
    },
    },
    },
    },
    (error, res, body) => {
    // console.log(res)
    }
    );
    });

    参考资料:
    https://github.com/expressjs/multer
    https://www.npmjs.com/package/request
    fengfuliu
        11
    fengfuliu  
       2022-10-22 13:30:19 +08:00
    @keji 非常感谢老哥 在我折腾一天后,你的回答帮我解决了问题
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5278 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 08:26 · PVG 16:26 · LAX 00:26 · JFK 03:26
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.