[已解决]Nodejs base64编码上传问题
[已解决]Nodejs base64编码上传问题
新手请教一个base64编码上传的问题,请各位大侠帮忙指点一下,多谢。
背景:
提供上传接口给终端的JS调用,因为JS没办法直接上传,所以是把文件转成base64编码传给我,我再调文件服务器上传
问题:
我现在是拿到base64的字符串以后转成buffer保存到本地临时文件,再读取文件上传
因为我没办法把base64的编码直接转成readStream…
这个方法感觉很挫…请教有什么好办法没?
以下是我的代码:
app.post('/uploadBase64', function(req, res) {
var base64Data = req.body.base64Data;
var fileName = req.body.fileName;
var tempFilePath = path.join(__dirname, fileName);
// 用request上传文件
var r = request.post('http://文件服务器', function(error, response, body) {
// 上传完以后删除临时文件
fs.unlink(tempFilePath);
res.send({
media_id: JSON.parse(body).media_id
});
});
// base64保存为临时文件
fs.writeFileSync(tempFilePath, new Buffer(base64Data, 'base64'));
var form = r.form();
form.append('media', fs.createReadStream(tempFilePath));
});
当然可以。根据你描述的需求,我们可以优化你的代码,使其更加高效且避免创建临时文件。我们可以通过将Base64字符串直接转换为Readable Stream
来实现这一点。
下面是改进后的代码示例:
const express = require('express');
const request = require('request');
const app = express();
app.use(express.json()); // 解析JSON格式的请求体
app.post('/uploadBase64', (req, res) => {
const base64Data = req.body.base64Data;
const fileName = req.body.fileName;
if (!base64Data || !fileName) {
return res.status(400).send({ error: 'Missing base64Data or fileName' });
}
try {
// 将Base64字符串转换为Buffer
const buffer = Buffer.from(base64Data, 'base64');
// 创建Readable Stream
const stream = buffer.createReadStream();
// 创建FormData对象用于上传
const formData = {
media: {
value: stream,
options: {
filename: fileName,
contentType: 'application/octet-stream'
}
}
};
// 使用request发送POST请求
request.post(
{ url: 'http://文件服务器', formData: formData },
(error, response, body) => {
if (error) {
return res.status(500).send({ error: 'Upload failed' });
}
const result = JSON.parse(body);
res.send({
media_id: result.media_id
});
}
);
} catch (err) {
console.error(err);
res.status(500).send({ error: 'Internal server error' });
}
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
解释
- 使用Express解析请求体:我们使用
express.json()
中间件来自动解析JSON格式的请求体。 - 检查请求参数:确保
base64Data
和fileName
存在,如果不存在则返回错误响应。 - Base64转Buffer:使用
Buffer.from(base64Data, 'base64')
将Base64字符串转换为Buffer。 - 创建Readable Stream:通过
buffer.createReadStream()
将Buffer转换为Readable Stream。 - FormData对象:创建一个FormData对象,其中包含
media
字段,该字段是一个包含Readable Stream的对象。 - 发送POST请求:使用
request.post
发送带有FormData的POST请求,并处理响应。 - 错误处理:添加适当的错误处理逻辑,确保在发生错误时能够返回合适的响应。
这种方法避免了创建临时文件的需要,从而提高了性能并减少了磁盘I/O操作。
终于搞定了…
buffer转stream用上面仁兄给的方法或者下面这个都行
http://stackoverflow.com/questions/13230487/converting-a-buffer-into-a-readablestream-in-nodejs
可是我试了很多次都有问题,传到后台以后变成字符串了
后来跟了一下代码,发现是form-data这个中间件影响的
下面这个是form-data的源码,可以看到他是根据path来判断的,因为我们自己转的stream没有path,所以就按照普通字符串处理了…
FormData.prototype._multiPartHeader = function(field, value) {
var boundary = this.getBoundary();
var header =
'--' + boundary + FormData.LINE_BREAK +
'Content-Disposition: form-data; name="' + field + '"';
// fs- and request- streams have path property
// TODO: Use request’s response mime-type
if (value.path) {
header +=
‘; filename="’ + path.basename(value.path) + ‘"’ + FormData.LINE_BREAK +
'Content-Type: ’ + mime.lookup(value.path);
// http response has not
} else if (value.readable && value.hasOwnProperty(‘httpVersion’)) {
header +=
‘; filename="’ + path.basename(value.client._httpMessage.path) + ‘"’ + FormData.LINE_BREAK +
'Content-Type: ’ + value.headers[‘content-type’];
}
header += FormData.LINE_BREAK + FormData.LINE_BREAK;
return header;
};
根据你的描述,你希望将前端通过 Base64 编码上传的文件直接处理并上传到文件服务器。这样做可以避免将 Base64 编码的数据写入磁盘然后再读取,从而提高效率。
这里有一个优化后的示例代码,使用 stream
和 buffer
直接从 Base64 编码的数据生成文件流并上传:
const express = require('express');
const request = require('request');
const app = express();
app.use(express.json()); // 解析JSON格式请求体
app.post('/uploadBase64', (req, res) => {
const base64Data = req.body.base64Data;
const fileName = req.body.fileName;
// 将Base64数据转换为Buffer
const buffer = Buffer.from(base64Data, 'base64');
// 创建文件流并将Base64数据写入
const fileStream = buffer.createReadStream();
// 文件上传请求
const uploadRequest = request.post(
{ url: 'http://文件服务器', formData: { media: fileStream } },
(error, response, body) => {
if (error) {
return res.status(500).send({ error });
}
res.send(JSON.parse(body));
}
);
// 设置文件名和内容类型(如果需要)
uploadRequest.form().append('filename', fileName);
// 无需创建临时文件
});
app.listen(3000, () => console.log('Server running on port 3000'));
这段代码使用了 Node.js 的 buffer
模块将 Base64 编码的字符串转换为 Buffer
对象,然后直接创建了一个文件流,并将其传递给文件服务器进行上传。这样就不需要在磁盘上创建临时文件,从而提高了性能和效率。