最近用vue做的项目中有用到一个图片上传,实时预览的功能;其中我用到了两个HTML5的新特性:FileReaderFormData

首先介绍下这两个方法:

HTML5定义了FileReader作为文件API的重要成员用于读取文件,根据W3C的定义,FileReader接口提供了读取文件的方法和包含读取文件结果的各类事件模型,想查看详细描述,请阅读FileReader

1.检测浏览器对FileReader兼容性的方法:

if(window.FileReader) {  
    var fr = new FileReader();  
    // add your code here  
}  
else {  
    alert("Not supported by your browser!");  
} 
/*方法二:检测FileReader类型*/
if(typeof FileReader==='undefined'){
    alert('您的浏览器不支持图片上传,请升级您的浏览器');
      return false;
 }

2.调用fileReader对象的方法 
FileReader实例拥有四个方法,其中三个是用来读取文件,另一个是用来中断读取的。需要注意的是,无论读取成功或是失败,方法并不会返回读取结果,这一结果(储存在result属性中)要用FileReader处理事件去获取;

方法名参数描述
abortnone中断读取
readAsBinaryStringfile将文件转化为二进制码
readAsDataURLfile将文件读取为DataURL
readAsTextfile,[encoding]将文件读取为文本

readAsText:该方法有两个参数,其中第二个参数是文本的编码方式,默认值为 UTF-8。这个方法非常容易理解,将文件以文本方式读取,读取的结果即是这个文本文件中的内容。 
readAsBinaryString:该方法将文件读取为二进制字符串,通常我们将它传送到后端,后端可以通过这段字符串存储文件。 
readAsDataURL:这是例子程序中用到的方法,该方法将文件读取为一段以 data: 开头的字符串,这段字符串的实质就是 Data URL,Data URL是一种将小文件直接嵌入文档的方案。这里的小文件通常是指图像与 html 等格式的文件。

3.处理事件 
FileReader 包含了一整套完成的事件模型,用于捕获读取文件时的状态,下面这个表格归纳了这些事件。

事件描述
onabort中断时触发
onerror出错时触发
onload文件读取成功完成时触发
onloadend读取完成时触发,无论读取成功或失败
onloadstart读取开始时触发
onprogress读取中

XMLHttpRequest Level 2添加了一个新的接口 - - - FormData 对象,我们可以通过 javascript 用一些键值对来模拟表单提交,我们还可以用XMLHttpRequest 的 send() 方法来异步的提交表单。与普通的 Ajax 相比,使用 FormData 的最大优点就是我们可以异步上传二进制文件。

创建一个FormData 对象

你可以创建一个空的FormData对象,然后使用append()方法想该对象添加字段,如下:

var oMyForm = new FormData();

oMyForm.append("username", "Groucho");
oMyForm.append("accountnum", 123456); // 数字123456被立即转换成字符串"123456"

// fileInputElement中已经包含了用户所选择的文件
oMyForm.append("userfile", fileInputElement.files[0]);

var oFileBody = "<a id="a"><b id="b">hey!</b></a>"; // Blob对象包含的文件内容
var oBlob = new Blob([oFileBody], { type: "text/xml"});

oMyForm.append("webmasterfile", oBlob);

var oReq = new XMLHttpRequest();
oReq.open("POST", "http://foo.com/submitform.php");
oReq.send(oMyForm);

注:字段 “userfile” 和 “webmasterfile” 的值都包含了一个文件。通过 FormData.append() 方法赋给字段 “accountnum” 的数字被自动转换为字符(字段的值可以是一个 Blob 对象,File对象或者字符串,剩下其他类型的值都会被自动转换成字符串)。 
在该例子中,我们创建了一个名为 oMyForm 的 FormData 对象,该对象中包含了名为”username”,”accountnum”,”userfile” 以及 “webmasterfile” 的字段名,然后使用XMLHttpRequest的 send() 方法把这些数据发送了出去。”webmasterfile” 字段的值不是一个字符串,还是一个 Blob 对象。

使用form表单初始化一个FormData对象

可以用一个已有的 form 元素来初始化 FormData 对象,只需要把这个 form 元素作为参数传入 FormData 构造函数即可:

var formElement = document.getElementById("myFormElement");
var oReq = new XMLHttpRequest();
oReq.open("POST", "submitform.php");
oReq.send(new FormData(formElement));

浏览器兼容性

FeatureChromeFirefox(Gecko)IEOperaSafari
Basic support7+4.0(2.0)10+12+5+
支持filename参数(yes)22.0(22.0)???

下面是我的项目代码:

<div class="issue-project-main clearfix" id='issue_project_main'>
<form  v-on:submit.prevent="submit_issue_project()" id="project_form">
       <div class="issue-project-left">
        <div v-if="images.length >0">
            <ul>
                <li v-for="(image,key) in images" style="position:relative;">
                    <img :src="image" @click='delImage(key)' class="image-upload"/>
                    <a href="#" class="remove-box" @click='delImage(key)'>
                        <span class="image-remove"></span>
                    </a>
                </li>
            </ul>
            <!-- <button @click="removeImage">移除全部图片</button> -->
            <!-- <button @click='uploadImage' >上传</button> -->
        </div> 
        <div v-show="showbutton">
            <a id='addPic' href="" v-on:click="addPic">上传项目图片 </a>
            <input type="file" id="imagebox" v-on:change="getImage()"     @change="onFileChange" name="image" style="display: none;">
        </div>
    </div>
   <div class="issue-project-form-list issue-project-form-btn">
                  <p class='errormsg' v-text='errormsg'></p>
                  <div class="mask-submit" v-if='disabled'></div>
                  <input type="submit" class="issue-project-btn" value="完成"/>
                  <input type="button" class="cancel-project-btn" value="取消" @click='back' />
              </div>
          </div>
      </form>
 </div>

js代码:

 var issue_project = new Vue({
        el:'#issue_project_main',
        data:{
            showbutton:true,
            disabled:false,
            url_ajax:'',
            images: []//显示的图片
        },
        watch:{
            images:function(){
                if(this.images.length >0){
                    this.showbutton = false
                }else{
                    this.showbutton = true
                }
            }
        },
        methods: {
            /*以下是上传图片的js*/
            getImage:function(){
                file = $("#imagebox")[0].value
            },
            addPic:function(e){
                e.preventDefault();
                $('input[type=file]').trigger('click');
                return false;
            },
            onFileChange:function(e) {
                var files = e.target.files || e.dataTransfer.files;
                if (!files.length)return; 
                this.createImage(files);
            },
            createImage:function(file) {
                if(typeof FileReader==='undefined'){
                    alert('您的浏览器不支持图片上传,请升级您的浏览器');
                    return false;
                }
                var image = new Image();         
                var vm = this;
                var leng=file.length;
                for(var i=0;i<leng;i++){
                    var reader = new FileReader();
                    reader.readAsDataURL(file[i]); 
                    reader.onload =function(e){
                    vm.images.push(e.target.result);                                    
                    };                 
                }                        
            },
            delImage:function(index){
                this.images.shift(index);
            },
            removeImage: function(e) {
                this.images = [];
            },
            /*以上是上传图片的js*/
            submit_issue_project:function(){
                var _this = this;
                _this.url_ajax = '/vdg/api/project/create'
                if(edit){
                    _this.url_ajax = '/vdg/api/project/update'
                }
                var formElement = document.getElementById("project_form");
                var formData = new FormData(formElement);
                axios({
                    method: 'post',
                    url: _this.url_ajax,
                    data: formData,
                    headers: {
                        'Content-Type': 'multipart/form-data'
                    },
                }).then(function(res){
                    console.log(res);
                }).catch(function(error) {
                    console.log(error);
                });
            }
        },
    })