你真的了解文件上传吗?

335 阅读2分钟

大家都知道文件上传,通过nodejs获取的数据是非常困难的。

错误的上传处理

直接将请求体中的内容存入到本地文件中。

    const http = require('http');
    const fs = require('fs');

    const server = http.createServer((req, res) => {
      let body = ""
      if (req.url === '/upload') {
        if (req.method === 'POST') {
          // const fileWriter = fs.createWriteStream('./foo.png', {flags: 'a+'});
          // req.pipe(fileWriter);

          req.on('data', (data) => {
            body += data
            // fileWriter.write(data);
          });

          req.on('end', () => {
            console.log(body)// 输出一大堆东西
            console.log("文件上传成功~");
            res.end("文件上传成功~");
          })
        }
      }
    });

    server.listen(8000, () => {
      console.log("文件上传服务器开启成功~");
    })

image.png 上面错误处理的原因是,将请求体中的内容都当成了该图片的内容,其实他还存在数据类型,上传的文件名,每个上传文件的分割内容。所以保存的文件是不正确的,不能打开的。

正确的上传处理

通过一步步的分割字符串,来截取正确的文件内容,然后再存入本地。

  • 在处理数据的时候一定要设置二进制编码req.setEncoding('binary'),不然截取文件存入后,会产生乱码导致文件出错。
  • querystring的parse方法,参数一:操作的字符串,参数二:字符串分割符,参数三:键值对分隔符。
  • 然后就是获取文件分隔符boundary。 image.png
  • 最后照着上图将括起来的部分删除即可。
  const totalBoundary = req.headers['content-type'].split(';')[1];
  const boundary = totalBoundary.split('=')[1];
    const http = require('http');
    const fs = require('fs');
    const qs = require('querystring');

    const server = http.createServer((req, res) => {
      if (req.url === '/upload') {
        if (req.method === 'POST') {
          req.setEncoding('binary');

          let body = '';
          const totalBoundary = req.headers['content-type'].split(';')[1];
          const boundary = totalBoundary.split('=')[1];

          req.on('data', (data) => {
            body += data;
          });

          req.on('end', () => {
            console.log(body);
            // 处理body
            // 1.获取image/png的位置
            const payload = qs.parse(body, "\r\n", ": ");
            const type = payload["Content-Type"];

            // 2.开始在image/png的位置进行截取
            const typeIndex = body.indexOf(type);
            const typeLength = type.length;
            let imageData = body.substring(typeIndex + typeLength);

            // 3.将中间的两个空格去掉
            imageData = imageData.replace(/^\s\s*/, '');

            // 4.将最后的boundary去掉
            imageData = imageData.substring(0, imageData.indexOf(`--${boundary}--`));

            fs.writeFile('./foo.png', imageData, 'binary', (err) => {
              res.end("文件上传成功~");
            })
          })
        }
      }
    });

    server.listen(8000, () => {
      console.log("文件上传服务器开启成功~");
    })

如你所见,争取的截取一个文件的内容是非常麻烦的,所以工作中我们一般会使用第三方库multer详细用法请访问这里