YBFACC / blog

仅记录个人学习使用
3 stars 0 forks source link

Form #19

Open YBFACC opened 4 years ago

YBFACC commented 4 years ago

表单

我的代码

常见的表单提交 Header:

GET方式提交表单

原生表单会以key=value的方式拼接在url后面。

例如以下代码:

  <form action="/get" method="GET" >
    <input type="text" name="name1" id="id1" value="">
    <button type="submit">GET</button>
  </form>

点击提交后,跳转到新页面并看到url变化。

1

application/x-www-form-urlencoded

这是原生表单的默认的提交格式。

  <form action="/post" method="POST">
    <input type="text" name="name1" value="">
    <input type="text" name="name2" value="">
    <input type="text" name="name3" value="">
    <button type="submit">POST</button>
  </form>

我们可以在后端拿到类似url的数据格式。

2

解析即可。

multipart/form-data

可以用来上传文件。

  <form action="/post" method="POST" enctype="multipart/form-data">
    <input type="text" name="name1" value="">
    <input type="text" name="name2" value="">
    <input type="text" name="name3" value="">
    <button type="submit">POST</button>
  </form>

点击按钮上传时,会发现 Content-Type: 的值有些不一样。

3

指明 multipart/form-data 很正常。但是后面的 boundary=---WebKitFormBoundaryCkL35Iut5A3hdvGD 就比较奇怪。

在MDN中解释到:

boundary:用于封装消息的多个部分的边界

4

可以看到我们上传的格式相对于 x-www-form-urlencoded 有所改变。

上传图片

  <form action="/post" method="POST" enctype="multipart/form-data">
    <input type="file" name="img">
    <button type="submit">POST</button>
  </form>

我选择 一张图片进行上传。

注意接收时,选择二进制流而不是UTF-8。

以下代码来自Node.js HTTP服务器中不依赖第三方模块的文件、图片上传

function parseFile (req, res) {
  req.setEncoding('binary'); 
  var body = '';   // 文件数据
  var fileName = '';  // 文件名
  // 边界字符串
  var boundary = req.headers['content-type'].split('; ')[1].replace('boundary=','');
  req.on('data', function(chunk){
    body += chunk;
  });

  req.on('end', function() {      
    var file = querystring.parse(body, '\r\n', ':')

    // 只处理图片文件
    if (file['Content-Type'].indexOf("image") !== -1)
    {   
      //获取文件名
      var fileInfo = file['Content-Disposition'].split('; ');
      for (value in fileInfo){
        if (fileInfo[value].indexOf("filename=") != -1){
          fileName = fileInfo[value].substring(10, fileInfo[value].length-1); 

          if (fileName.indexOf('\\') != -1){
            fileName = fileName.substring(fileName.lastIndexOf('\\')+1);
          }
          console.log("文件名: " + fileName); 
        }   
      }

      // 获取图片类型(如:image/gif 或 image/png))
      var entireData = body.toString();           
      var contentTypeRegex = /Content-Type: image\/.*/;

      contentType = file['Content-Type'].substring(1); 

      //获取文件二进制数据开始位置,即contentType的结尾
      var upperBoundary = entireData.indexOf(contentType) + contentType.length; 
      var shorterData = entireData.substring(upperBoundary); 

      // 替换开始位置的空格
      var binaryDataAlmost = shorterData.replace(/^\s\s*/, '').replace(/\s\s*$/, '');

      // 去除数据末尾的额外数据,即: "--"+ boundary + "--"
      var binaryData = binaryDataAlmost.substring(0, binaryDataAlmost.indexOf('--'+boundary+'--'));        

      // 保存文件
      fs.writeFile(fileName, binaryData, 'binary', function(err) {
        es.end('图片上传完成');
      });
    } else {
      res.end('只能上传图片文件'); 
    }
  });
}

参考

Node.js HTTP服务器中不依赖第三方模块的文件、图片上传

玩转Koa -- koa-bodyparser原理解析