前端上传文件的2种方式

224 阅读1分钟

1、通过表单form上传

<template>
<div>
    用form上传
    <form ref="form" action="http://localhost:3000/" method="post" enctype="multipart/form-data" target="iframe">
        <input name="uploadFile" type="file" accept="image/png, image/jpeg" />
        <input type="button" value="提交" @click="handleSubmit" />
    </form>
    <iframe name="iframe" style="display:none"></iframe>
</div>
</template>
<script>
export default {
    methods:{
        handleSubmit(){
            this.$refs.form.submit();
        }
    }
}
</script>

常见的post提交数据对应的Content-Type取值有4种
1、application/x-www-form-urlencoded
    form表单如果不设置enctype,就会以application/x-www-urlencoded方式, 形式为key1=val1&key2&val2,
    http的headers举例:Content-Type:application/x-www-form-urlencoded;charset=utf-8
2、mulipart/form-data
    上传文件上时,form标签的enctype需要设置成"multipart/form-data"
3、application/json
    告诉服务器消息主体是序列化后的JSON字符串,适合比键值对更复杂的结构化数据。
4、text/xml
    传输xml格式数据时用的到,现在以不常用。

注意:1、上传文件上时,form标签的enctype需要设置成"multipart/form-data"
             2、默认提交表单会跳转新页面,这里用了一个隐藏的iframe,表单的target提交到这个iframe里,就“阻止”了跳转新页面

1、通过FormData

<template>
<div>
    用FormDate上传
    <input ref='fileInput' type="file" />
    <input type="button" value="上传" @click="handleUpload" />
</div>
    
</template>
<script>
export default {
    methods:{
        handleUpload(){
            const formData = new FormData();
            formData.append('uploadFile', this.$refs.fileInput.files[0]);
            const xhr = new XMLHttpRequest();
            xhr.open('POST','http://localhost:3000', true);
            xhr.send(formData);
        }
    }
}
</script>

执行上传,查看chrome控制台,Content-Type已经有了mulipart/form-data

3、服务器端接收文件

const http = require('http');
const path = require('path');
const fs = require('fs');
const app = http.createServer((req, res) => {
  res.writeHead(200, {
    'Content-type': 'text/html;charset=UTF-8',
    'Access-Control-Allow-Origin': '*',
  });
  if (req.method.toLowerCase() == 'post') {
    //新建一个空数组接受流的信息
    var chunks = [];
    //获取长度
    let num = 0;

    req.on('data', function(chunk) {
      chunks.push(chunk);
      num += chunk.length;
    });
    req.on('end', function() {
      //最终流的内容本体
      var buffer = Buffer.concat(chunks, num);
      
      //新建数组接收出去\r\n的数据下标
      let rems = [];
      //根据\r\n分离数据和报头
      for (var i = 0; i < buffer.length; i++) {
        let v = buffer[i];
        let v2 = buffer[i + 1];
        // 10代表\n 13代表\r
        if (v == 13 && v2 == 10) {
          rems.push(i);
        }
      } //for
      //获取上传图片信息
      
      let picmsg_1 = buffer.slice(rems[0] + 2, rems[1]).toString();
      console.log(picmsg_1);
      let filename = picmsg_1.match(/filename=".*"/g)[0].split('"')[1];
      console.log(filename);

      //图片数据
      var nbuf = buffer.slice(rems[3] + 2, rems[rems.length - 2]);
      let address = './' + filename;
      //创建空文件并写入内容
      fs.writeFile(address, nbuf, function(err) {
        if (err) {
          console.log(err);
        } else {
          console.log('创建成功');
        }
      });
    });
    res.end();
  }
});

app.listen(3000, () => {
  console.log('server ok!');
});

先接收,拼接放Buffer实例里,再分离描述信息,拿到文件名,再提取纯文件信息,根据拿到的文件名来名命,写一个新的文件。