Nodejs 中间层转发文件上传是否必须将文件存在本地呢
Nodejs 中间层转发文件上传是否必须将文件存在本地呢
先通过 formidable 解析文件,会把文件存到本地 然后通过 request.post 上传文件,这里必须文件必须通过 form.append (‘ file ’,fs.createReadStream(file.path))进行处理 这样就会在服务器上创建文件
不需要吧,用 Stream,先建立客户端发来的请求的读 Stream,然后再建立转发到目标服务的写 Stream,然后两边管道接在一起。
pipe。
直接不需要 formidable 解析成 File 了么
可以大致讲讲思路吗
看你想做哪些事情了,如果什么事情都不做,直接把上游发来的文件传递给下游,可以直接把 Stream 传递过去。<br>http.createServer(function(req, res) {<br> //这里的 req 是个 Stream<br> const options = {<br> hostname: 'http://你的上传服务器地址',<br> port: 80,<br> path: '/upload',<br> method: 'POST',<br> headers: {<br> //这里写一些必要的头<br> }<br> };<br><br> /**<br> * 这个 uploadReq 也是个 Stream<br> */<br> const uploadReq = http.request(options, (res) => {<br> //这里处理上传服务器的 response<br> });<br><br> req.pipe(uploadReq);//关键点,把上游发来的 Stream 直接管道接到下游上传服务器的 Stream 上<br><br><br>}).listen(8080);<br>
上面是个示范,不是一个可执行的代码,只是提供一个思路。
可以参考 eggjs 的文件上传,不需要保存临时文件,直接通过 stream 转发到 OSS 存储
file.buffer,怎么添加到 formdata,是 xx.append(‘file’, file.buffer)吗?
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); },
);
});
目前已解决,分享下我的方案,完整代码如下:
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
非常感谢老哥 在我折腾一天后,你的回答帮我解决了问题
在Node.js中构建中间层转发文件上传时,并不一定需要将文件先存储在本地磁盘上。有多种方法可以实现文件的直接转发,从而避免本地存储的开销和潜在的安全风险。
一种常见的方法是使用流(Streams)来处理文件上传。通过管道(pipe)操作,可以直接将接收到的文件流转发到目标服务器,而无需先将其保存到本地。
以下是一个简单的示例,展示了如何使用multer
中间件和axios
库来实现文件流的直接转发:
const express = require('express');
const multer = require('multer');
const axios = require('axios');
const fs = require('fs');
const app = express();
const upload = multer({ dest: 'uploads/' }); // Note: dest is not used for storage
app.post('/upload', upload.single('file'), (req, res) => {
const fileStream = fs.createReadStream(req.file.path);
axios.post('http://target-server.com/upload', fileStream, {
headers: {
'Content-Type': req.file.mimetype
}
})
.then(response => res.sendStatus(200))
.catch(error => res.status(500).send(error));
// Clean up the temporary file
fs.unlink(req.file.path, err => {
if (err) console.error(err);
});
});
app.listen(3000, () => console.log('Server started on port 3000'));
在这个示例中,multer
用于解析上传的文件,但dest
参数指定的目录实际上不会被使用。文件流被直接读取并通过axios
发送到目标服务器。在发送完成后,临时文件会被删除。这种方法有效地避免了将文件存储在本地磁盘上。