[已解决]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));
});

4 回复

当然可以。根据你描述的需求,我们可以优化你的代码,使其更加高效且避免创建临时文件。我们可以通过将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');
});

解释

  1. 使用Express解析请求体:我们使用express.json()中间件来自动解析JSON格式的请求体。
  2. 检查请求参数:确保base64DatafileName存在,如果不存在则返回错误响应。
  3. Base64转Buffer:使用Buffer.from(base64Data, 'base64')将Base64字符串转换为Buffer。
  4. 创建Readable Stream:通过buffer.createReadStream()将Buffer转换为Readable Stream。
  5. FormData对象:创建一个FormData对象,其中包含media字段,该字段是一个包含Readable Stream的对象。
  6. 发送POST请求:使用request.post发送带有FormData的POST请求,并处理响应。
  7. 错误处理:添加适当的错误处理逻辑,确保在发生错误时能够返回合适的响应。

这种方法避免了创建临时文件的需要,从而提高了性能并减少了磁盘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 编码的数据写入磁盘然后再读取,从而提高效率。

这里有一个优化后的示例代码,使用 streambuffer 直接从 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 对象,然后直接创建了一个文件流,并将其传递给文件服务器进行上传。这样就不需要在磁盘上创建临时文件,从而提高了性能和效率。

回到顶部