如何将 multer 保存在内存中的文件上传到另一个 API
how to upload file saved in memory by multer to another API
我有 2 个单独的 NodeJS APIs,它使用 multer 将文件保存在 内存 中。
我的 express 中间件是这样的
import multer from 'multer';
const storage = multer.memoryStorage();
export default multer({ storage }).single('image');
我能够成功接收保存在内存中的文件,所以我的 req.file.image 看起来像这样
{
fieldname: 'image',
originalname: 'image-2017-08-28-13-47-31-218.png',
encoding: '7bit', mimetype: 'image/png',
buffer: <Buffer 89 50 4e 47 0d 0a 1a 0 ... >,
size: 493181
}
收到文件后,在第一API,我需要发送到第二API 也使用 multer & express
function secondApiReceiveImage(req, res) {
console.log(req.file)
console.log(req.files)
console.log(req.body)
res.send('ok');
}
我尝试使用以下实现发送
通过https://github.com/request/request#multipartform-data-multipart-form-uploads
import request from 'request';
function firstApiReceiveImage(req, res) {
const options = {
url:'http://SECOND_API/api/image',
formData: { image: req.file.buffer }
};
request.post(options, (err, httpResponse, body) => {
console.log('err', err);
console.log('body', body);
});
}
在这种情况下,req.file、req.files 和 [ 的日志=83=] 都是 undefined on secondApiReceiveImage API handler函数
我的下一次尝试是 https://github.com/form-data/form-data
import multer from 'multer';
const storage = multer.memoryStorage();
export default multer({ storage }).single('image');
function firstApiReceiveImage(req, res) {
const CRLF = '\r\n';
const form = new FormData();
const opts = {
header: `${CRLF} + '--' + ${form.getBoundary()} + ${CRLF} + 'X-Custom-Header: 123' + ${CRLF} + ${CRLF}`,
knownLength: 1
};
form.append('image', req.file.image.buffer, opts);
form.submit('http://SECOND_API/api/image', (err, res) => {
console.log('err', err);
console.log('res', res);
});
}
我得到了相同的结果,undefined for req.file, req.files &req.body第二个API
除了 multer BTW
,这些是我的两个 API 的中间件
app.use(compression());
app.use(helmet());
app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
如果我可以先将文件保存在 API 上,我的生活可能会更轻松,但在这种情况下我们不允许保存到磁盘: (
对我有什么建议吗?
使用 Request,formdata
应该设置为 buffer:
formData: { image: req.file.buffer }
团队通过先将缓冲区转换为 Stream 并以不同方式发送表单数据来解决这个问题。
import stream from 'stream';
import rq from 'request-promise';
const { Duplex } = stream;
function bufferToStream(buffer) {
const duplexStream = new Duplex();
duplexStream.push(buffer);
duplexStream.push(null);
return duplexStream;
}
async function store({
originalname, mimetype, size, buffer,
}) {
logger.debug(`Saving image name:${originalname} type:${mimetype} size:${size}`);
const formData = {
image: {
value: bufferToStream(buffer),
options: {
filename: originalname,
contentType: mimetype,
knownLength: size,
},
},
};
const options = Object.assign({}, IMAGE_SAVE_ENDPOINT, { formData });
const response = await rq(options);
return response.id;
}
我找到了通过缓冲区使用 multer 上传文件而不是在本地存储的方法...
这是我的代码....
var multer = require('multer');
var storage= multer.memoryStorage();
var upload = multer({storage: storage});
var cloudinary = require('cloudinary');
cloudinary.config({
cloud_name: 'your-cloud-name',
api_key: process.env.CLOUDINARY_API_KEY, //your api-key
api_secret: process.env.CLOUDINARY_API_SECRET //your api-secret
});
如上配置你的 cloudinary 和 multer.....
从请求中获取缓冲区如下..
router.post("/",upload.single('image'),function(req,res){
var buf = req.file.buffer.toString('base64');
// Upload code Here
)};
上传代码:
cloudinary.uploader.upload("data:image/png;base64," + buf, function(result) {
//your code here
console.log(result);
},{
folder: 'folder-name' //if you want to store in a folder
});
结果输出如下:
{
asset_id: 'ed58484fb2bdce823f1b27d*******8',
public_id: '**************',
version: 1594455479,
version_id: '68450****88842ce0aa319603e68d3',
signature: '3785dbfc3**********883720b',
width: 750,
height: 500,
format: 'png',
resource_type: 'image',
created_at: '2020-07-11T08:17:59Z',
tags: [],
pages: 1,
bytes: 70846,
type: 'upload',
etag: 'd04dd691de532e941faccda846ef3d76',
placeholder: false,
url: 'http://res.cloudinary.com/*****************',
secure_url: 'https://res.cloudinary.com/*******************'
}
我偶然发现了同样的问题,这是我设法想出的。
首先,我使用 form-data 包来模拟服务器端的 FormData 数据结构,这里是执行此操作的 util 文件。
const FormData = require('form-data')
const formData = new FormData()
const config = {
headers: {
'Content-Type': `multipart/form-data; boundary=${formData.getBoundary()}`
}
}
export default { data: formData, config }
这是我的 node.js api 文件
import formSet from '../utils/formData'
const multer = require('multer')
const upload = multer()
const { Router } = require('express')
const router = Router()
......
router.post('/api/images', upload.single('image'), async (req, res) => {
formSet.data.append('image', req.file.buffer, { filename: req.file.originalname })
formSet.data.append('other_data', 'value')
const response = await axios.post('/images', formSet.data, formSet.config)
.......
})
我有 2 个单独的 NodeJS APIs,它使用 multer 将文件保存在 内存 中。
我的 express 中间件是这样的
import multer from 'multer';
const storage = multer.memoryStorage();
export default multer({ storage }).single('image');
我能够成功接收保存在内存中的文件,所以我的 req.file.image 看起来像这样
{
fieldname: 'image',
originalname: 'image-2017-08-28-13-47-31-218.png',
encoding: '7bit', mimetype: 'image/png',
buffer: <Buffer 89 50 4e 47 0d 0a 1a 0 ... >,
size: 493181
}
收到文件后,在第一API,我需要发送到第二API 也使用 multer & express
function secondApiReceiveImage(req, res) {
console.log(req.file)
console.log(req.files)
console.log(req.body)
res.send('ok');
}
我尝试使用以下实现发送
通过https://github.com/request/request#multipartform-data-multipart-form-uploads
import request from 'request';
function firstApiReceiveImage(req, res) {
const options = {
url:'http://SECOND_API/api/image',
formData: { image: req.file.buffer }
};
request.post(options, (err, httpResponse, body) => {
console.log('err', err);
console.log('body', body);
});
}
在这种情况下,req.file、req.files 和 [ 的日志=83=] 都是 undefined on secondApiReceiveImage API handler函数
我的下一次尝试是 https://github.com/form-data/form-data
import multer from 'multer';
const storage = multer.memoryStorage();
export default multer({ storage }).single('image');
function firstApiReceiveImage(req, res) {
const CRLF = '\r\n';
const form = new FormData();
const opts = {
header: `${CRLF} + '--' + ${form.getBoundary()} + ${CRLF} + 'X-Custom-Header: 123' + ${CRLF} + ${CRLF}`,
knownLength: 1
};
form.append('image', req.file.image.buffer, opts);
form.submit('http://SECOND_API/api/image', (err, res) => {
console.log('err', err);
console.log('res', res);
});
}
我得到了相同的结果,undefined for req.file, req.files &req.body第二个API
除了 multer BTW
,这些是我的两个 API 的中间件app.use(compression());
app.use(helmet());
app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
如果我可以先将文件保存在 API 上,我的生活可能会更轻松,但在这种情况下我们不允许保存到磁盘: (
对我有什么建议吗?
使用 Request,formdata
应该设置为 buffer:
formData: { image: req.file.buffer }
团队通过先将缓冲区转换为 Stream 并以不同方式发送表单数据来解决这个问题。
import stream from 'stream';
import rq from 'request-promise';
const { Duplex } = stream;
function bufferToStream(buffer) {
const duplexStream = new Duplex();
duplexStream.push(buffer);
duplexStream.push(null);
return duplexStream;
}
async function store({
originalname, mimetype, size, buffer,
}) {
logger.debug(`Saving image name:${originalname} type:${mimetype} size:${size}`);
const formData = {
image: {
value: bufferToStream(buffer),
options: {
filename: originalname,
contentType: mimetype,
knownLength: size,
},
},
};
const options = Object.assign({}, IMAGE_SAVE_ENDPOINT, { formData });
const response = await rq(options);
return response.id;
}
我找到了通过缓冲区使用 multer 上传文件而不是在本地存储的方法... 这是我的代码....
var multer = require('multer');
var storage= multer.memoryStorage();
var upload = multer({storage: storage});
var cloudinary = require('cloudinary');
cloudinary.config({
cloud_name: 'your-cloud-name',
api_key: process.env.CLOUDINARY_API_KEY, //your api-key
api_secret: process.env.CLOUDINARY_API_SECRET //your api-secret
});
如上配置你的 cloudinary 和 multer.....
从请求中获取缓冲区如下..
router.post("/",upload.single('image'),function(req,res){
var buf = req.file.buffer.toString('base64');
// Upload code Here
)};
上传代码:
cloudinary.uploader.upload("data:image/png;base64," + buf, function(result) {
//your code here
console.log(result);
},{
folder: 'folder-name' //if you want to store in a folder
});
结果输出如下:
{
asset_id: 'ed58484fb2bdce823f1b27d*******8',
public_id: '**************',
version: 1594455479,
version_id: '68450****88842ce0aa319603e68d3',
signature: '3785dbfc3**********883720b',
width: 750,
height: 500,
format: 'png',
resource_type: 'image',
created_at: '2020-07-11T08:17:59Z',
tags: [],
pages: 1,
bytes: 70846,
type: 'upload',
etag: 'd04dd691de532e941faccda846ef3d76',
placeholder: false,
url: 'http://res.cloudinary.com/*****************',
secure_url: 'https://res.cloudinary.com/*******************'
}
我偶然发现了同样的问题,这是我设法想出的。
首先,我使用 form-data 包来模拟服务器端的 FormData 数据结构,这里是执行此操作的 util 文件。
const FormData = require('form-data')
const formData = new FormData()
const config = {
headers: {
'Content-Type': `multipart/form-data; boundary=${formData.getBoundary()}`
}
}
export default { data: formData, config }
这是我的 node.js api 文件
import formSet from '../utils/formData'
const multer = require('multer')
const upload = multer()
const { Router } = require('express')
const router = Router()
......
router.post('/api/images', upload.single('image'), async (req, res) => {
formSet.data.append('image', req.file.buffer, { filename: req.file.originalname })
formSet.data.append('other_data', 'value')
const response = await axios.post('/images', formSet.data, formSet.config)
.......
})