美文网首页
前端文件上传方式

前端文件上传方式

作者: 毒行影客 | 来源:发表于2019-06-24 15:10 被阅读0次

     一丶前端文件上传方式

    前端网页文件上传一般使用 <input type="file" />来实现。

        在 HTML 文档中: `<input type="file" />`标签每出现一次,一个 FileUpload 对象就会被创建。该标签包含一个文本输入字段,用来输入文件名,还有一个按钮,用来打开文件选择对话框以便图形化选择文件,该标签的 value属性保存了用户指定的文件的名称。

                          多选: 标签可以通过添加 multiple 属性来支持多选;如果选择了多个文件, 这个值表示第一个被选择的文件路径. JavaScript 可以通过 Input 的 FileList属性获取到其他的文件路径.

                    文件信息:可以通过 input.files 属性返回 — 返回值是一个 FileList 对象,这个对象是一个包含了许多 File 文件的列表,列表包含图片的name,type,size                                    等属性。

            限制文件类型:你可以使用 input 的 accept 属性,accept 属性接受一个逗号分隔的 MIME 类型字符串。如: accept="image/png, image/jpeg" or accept=".png, .jpg, .jpeg" — PNG/JPEG

                    选择文件:会触发input的onchange事件;

                          上传:上传文件前 使用FileReader对象读取指定file的文件,并将文件转换为二进制字符串, 并将xhr对象, overrideMimeType 属性设置为text/plain;  charset=x-user-defined-binary, 最终后台接收到二进制后再做具体处理。

     第一种:经典的form和input上传

    设置form的aciton为后端页面,必填项:enctype="multipart/form-data",type=‘post’

        <form action='uploadFile.php' enctype="multipart/form-data" type='post'>

          <input type='file'>

          <input type='hidden' name='userid'>

          <input type='hidden' name='signature'>

          <button>提交</button>

        </form>

    使用input选择文件,设置好其他input的值,点击提交,将文件数据及签名等认证信息发送到form设置的action对应的页面,浏览器也会跳转到该页面。触发form表单提交数据的方式有2种,一种是在页面上点击button按钮或<input type='submit'>按钮触发,第二种是在js中执行form.submit()方法。

    优点:使用简单方便,兼容性好,基本所有浏览器都支持。

    缺点: 1. 提交数据后页面会跳转(下面会讲如何禁止页面跳转)。

        2.因为是浏览器发起的请求,不是一个ajax,所以前端无法知道什么时候上传结束。

          3. form表单里发送除文件外的数据,一般是新建一个type=hidden的input,value=‘需要传的数据’,每发送一个数据就需要一个input,一旦多了就会使得dom看起来比较冗余。

    小技巧:

    form表单提交数据后会自动跳转到action指定的页面,为了禁止页面跳转,可以在页面中新建一个空的ifame,比如name='upload',然后设置form的target="Uploader",form有一个target的属性,规定在何处打开action,这样form提交数据后就会仍停留在当前页。代码如下:

        <form action='uploadFile.url' enctype="multipart/form-data" type='post' target="uploaderPage">

             <input type='file'>

            button>提交</button>

        </form>

        <ifrmae name='upload' id='uploaderPage'></iframe>

    这样写的另一个好处是,可以知道什么时候上传完成并接收到后端的回调结果。比如上面这个例子,文件数据发送到了 'uploadFile.url',假设该页面处理完数据后返回了一个地址,该地址会被写入到之前的iframe中。所以在ifame的onload函数触发时,也就是上传完成后,可以在iframe中读取到后端返回的数据。

        var iframe = document.getElementById('uploadPage');

        iframe.onload = function () {

             var doc = window.frames['uploaderPage'].document;

             var pre = doc.getElementsByTagName('pre');

             var obj = JSON.parse(pre[0].innerHTML);

        }

    使用这种方法时需要注意,iframe有跨域限制,创建出来的iframe的地址如果和当前页面地址不同源,会报错。这种情况下,建议大家在iframe的onload函数中,再次向后端请求一个接口获取文件地址,而不是直接去iframe里读取。或者返回这样的数据。

        <script type="text/javascript">

             window.top.window.callback(data)

        </script>

    callback是和前端约定好的名字,上传完成后触发该函数并返回后端数据。

     第二种:使用formData上传。(分借用form和不借用form)

      借助form的ajax文件上传

        <script src="jquery.min.js"></script>

        <form id="uploadForm" enctype="multipart/form-data">

            <input type="file" name="file" id="file">

            <input type="button" value="Upload" id="upload" />

        </form>

        <script>

            $(function () {

                $('#upload').click(function () {

                    $.ajax({

                        url: "http://localhost:8080/img",

                        type: "post",

                        data: new FormData($('#uploadForm')[0]),

                        cache: false,

                        processData: false,

                        contentType: false,

                        success: function (res) {

                        console.log(res)

                        },

                        error: function (err) {

                            console.log(err)

                        }

                    })

                })

            })

        </script>

    processData设置为false。因为data值是FormData对象,不需要对数据做处理。

    `<form>`标签添加enctype="multipart/form-data"属性。

    cache设置为false,上传文件不需要缓存。

    contentType设置为false。因为是由`<form>`表单构造的FormData对象,且已经声明了属性enctype="multipart/form-data",所以这里设置为false。

    不借助form的ajax文件上传

        <input type="file" name="file" id="file"><input type="button" value="Upload" id="upload" />

        <script src="jquery.min.js"></script>

        <script>

        $(function () {

            $('#upload').click(function () {

                let file = $("#file")[0].files[0];

                //创建formdata对象

                let formData = new FormData();

                formData.append("file", file);

                $.ajax({

                    url: "http://localhost:8081/images",

                    type: "post",

                    data: formData,

                    cache: false,

                    processData: false,

                    contentType: false,

                    // headers: { 'Content-Type': 'multipart/form-data' },

                    success: function (res) {

                        console.log(res)

                    },

                    error: function (err) {

                        console.log(err)

                    }

                })

          })

        })

        </script>

    append()的第二个参数应是文件对象,即`$('#file')[0].files[0]`。

    contentType也要设置为‘false’。

    从代码`$('#file')[0].files[0]`中可以看到一个`<input type="file">`标签能够上传多个文件, 只需要在`<input type="file">`里添加multiple或multiple="multiple"属性。

    用js构造form表单的数据,简单高效,但最低只兼容IE10,所以需要兼容IE9的童鞋们就略过这个方法吧。

          html:

            <input type='file'>

            js:

            var formData = new FormData();

            formData.append("userid", userid);

            formData.append("signature", signature);

            formData.append("file", file); //file是blob数据

         //再用ajax发送formData到服务器即可,注意一定要是post方式上传

    说明:第一种方法提到了创建多个type=‘hidden’的input来发送签名数据,这儿可以用formData.append方法来代替该操作,避免了dom中有多个input的情况出现。最后将file数据也append到formData发送到服务器即可完成上传。

    优点:由于这种方式是ajax上传,可以准确知道什么时候上传完成,也可以方便地接收到回调数据。

    缺点:兼容性差

    第三种:使用fileReader读取文件数据进行上传。

    HTML5的新api,兼容性也不是特别好,只兼容到了IE10。

        var fr = new FileReader();

        fr.readAsDataURL(file);

        fr.onload = function (event) {

        var data= event.target.result; //此处获得的data是base64格式的数据

                            img.src = data;

        ajax(url,{data} ,function(){})

        }

    上面获得的data可以用来实现图片上传前的本地预览,也可以用来发送base64数据给后端然后返回该数据块对应的地址。

    优点: 同第二种

    缺点:一次性发送大量的base64数据会导致浏览器卡顿,服务器端接收这样的数据可能也会出现问题

    第四种:flash上传 参考jQuery封装好的uploadify插件

        <div id="file_upload"></div>

    html部分很简单,预留一个hook后,插件会在这个节点内部创建Flash的object,并且还附带创建了上传进度、取消控件和多文件队列展示等界面。

        $(function() {

        $("#file_upload").uploadify({

           auto: true,

          method: "Post",

          width: 120,

           height: 30,

           swf: './uploadify.swf',

             uploader: 'http://uploadUrl',

      formData: {

           token: $("#token").val()

        },

        fileObjName: "file",

        onUploadSuccess: function(file, data, response){

        // 根据返回结果指定界面操作

        }

        });

        });

    关于jQuery.uploadify可以访问了解: http://www.uploadify.com/documentation/ 。值得注意的是flash并不适合手机端应用,更好的解决方案是使用flash+html5来解决平台的兼容性问题。

    二丶图片上传和预览

     方法一:使用js的FileReader对象

    1、FileReader对象简介

    1.检测浏览器对FileReader的支持

        if(window.FileReader) {

             var fr = new FileReader();

            // add your code here

        }else {

            alert("Not supported by your browser!");

        }

    调用FileReader对象的方法

    FileReader 的实例拥有 4 个方法,其中 3 个用以读取文件,另一个用来中断读取。下面的表格列出了这些方法以及他们的参数和功能,

    需要注意的是 ,无论读取成功或失败,方法并不会返回读取结果,这一结果存储在 result属性中。

        方法名                          参数                      描述

        abort                              none                    中断读取

        readAsBinaryString        file                       将文件读取为二进制码

        readAsDataURL            file                         将文件读取为 DataURL

        readAsText                   file, [encoding]          将文件读取为文本

    readAsText:该方法有两个参数,其中第二个参数是文本的编码方式,默认值为 UTF-8。这个方法非常容易  

    理解,将文件以文本方式读取,读取的结果即是这个文本文件中的内容。

    readAsBinaryString:该方法将文件读取为二进制字符串,通常我们将它传送到后端,后端可以通过这段字符串存储文件。

    readAsDataURL:这是例子程序中用到的方法,该方法将文件读取为一段以 data: 开头的字符串,这段字符 串的实质就是 Data URL,Data URL是一种将小文件直接嵌入文档的方案。这里的小文件通常是指图像与 html 等格式的文件。(其中base64的方式就是由此来获得的。。)

    2. FileReader处理事件简介

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

    onabort        中断时触发

    onerror          出错时触发

    onload          文件读取成功完成时触发

    onloadend    读取完成触发,无论成功或失败

    onloadstart    读取开始时触发

    onprogress    读取中

    文件一旦开始读取,无论成功或失败,实例的 result 属性都会被填充。如果读取失败,则 result 的值为 null ,否则即是读取的结果,绝大多数的程序都会在成功读取文件的时候,抓取这个值。

    <p>

                <label>请选择一个文件:</label>

                <input type="file" id="file" />

                <input type="button" value="读取图像" onclick="readAsDataURL()" />

                <input type="button" value="读取二进制数据" onclick="readAsBinaryString()" />

                <input type="button" value="读取文本文件" onclick="readAsText()" />

            </p>

            <div id="result" name="result"></div>

            <script type="text/javascript">

                var result = document.getElementById("result");

                var file = document.getElementById("file");

                //判断浏览器是否支持FileReader接口

                if (typeof FileReader == 'undefined') {

                    result.InnerHTML = "<p>你的浏览器不支持FileReader接口!</p>";

                    //使选择控件不可操作

                    file.setAttribute("disabled", "disabled");

                }

                function readAsDataURL() {

                    //检验是否为图像文件

                    var file = document.getElementById("file").files[0];

                    if (!/image\/\w+/.test(file.type)) {

                        alert("看清楚,这个需要图片!");

                        return false;

                    }

                    var reader = new FileReader();

                    //将文件以Data URL形式读入页面

                    reader.readAsDataURL(file);

                    reader.onload = function (e) {

                        var result = document.getElementById("result");

                        //显示文件

                        result.innerHTML = '<img src="' + this.result + '" alt="" />';

                    }

                }

                function readAsBinaryString() {

                    var file = document.getElementById("file").files[0];

                    var reader = new FileReader();

                    //将文件以二进制形式读入页面

                    reader.readAsBinaryString(file);

                    reader.onload = function (f) {

                        var result = document.getElementById("result");

                        //显示文件

                        result.innerHTML = this.result;

                    }

                }

                function readAsText() {

                    var file = document.getElementById("file").files[0];

                    var reader = new FileReader();

                    //将文件以文本形式读入页面

                    reader.readAsText(file);

                    reader.onload = function (f) {

                        var result = document.getElementById("result");

                        //显示文件

                        result.innerHTML = this.result;

                    }

                }

            </script>

    3 、使用js的FileReader对象实现上传图片时的图片预览功能

        <!DOCTYPE html>

        <html>

        <head>

            <meta name="viewport" content="width=device-width,initial-scale=1, user-scalable=no">

            <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

            <meta name="format-detection" content="telephone=no">

            <title>test</title>

            <script>

                //选择图片时预览功能

                function imageshow(source) {

                    var file = source.files[0];

                    var imageid = source.id;

                    if (window.FileReader) {

                        var fr = new FileReader();

                        fr.onloadend = function (e) {

                            document.getElementById("portrait" + imageid).src = e.target.result;

                        };

                        fr.readAsDataURL(file);

                    }

                    document.getElementById("image" + imageid).style.display = "none";

                    document.getElementById("show" + imageid).style.display = "block";

                }

            </script>

        </head>

        <body>

            <div>

                <div id="image1">

                          <p>上传截图</p>

                    <input type="file" name="screenshot1" id="1" onchange="imageshow(this)" />

                </div>

                    <div id="show1" style="display:none;">

                          <img src="" id="portrait1" width="100" height="70">

                        </div>

                    <div id="image2">

                    <p>上传截图</p>

                    <input type="file" name="screenshot2" id="2" onchange="imageshow(this)" />

                </div>

                    <div id="show2" style="display:none;">

                          <img src="" id="portrait2" width="100" height="70">

                       </div>

                <div id="image3">

                    <p>上传截图</p>

                    <input type="file" name="screenshot3" id="3" onchange="imageshow(this)" />

                </div>

                  <div id="show3" style="display:none;">

                          <img src="" id="portrait3" width="100" height="70">

                        </div>

            </div>

        </body>

        </html>

    方法二:使用window.createObjectURL

    直接上代码:

        <!DOCTYPE html>

        <html>

        <head>

            <title>图片上传预览</title>

            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

            <script src="http://www.codefans.net/ajaxjs/jquery-1.6.2.min.js"></script>

        </head>

        <body>

            <form name="form0" id="form0">

                <input type="file" name="file0" id="file0" multiple="multiple" />

                <br>

                <img src="" width="100" height="100" id="img0">

            </form>

            <script>

                $("#file0").change(function () {

                    var objUrl = getObjectURL(this.files[0]);

                    console.log("objUrl = " + objUrl);

                    if (objUrl) {

                        $("#img0").attr("src", objUrl);

                    }

                });

                //取得该文件的url function getObjectURL(file) {

                var url = null;

                if (window.createObjectURL != undefined) {

                    url = window.createObjectURL(file);

                } else if (window.URL != undefined) {

                    url = window.URL.createObjectURL(file);

                } else if (window.webkitURL != undefined) {

                    url = window.webkitURL.createObjectURL(file);

                }

                return url;

        //}

            </script>

        </body>

        </html>

    相关文章

      网友评论

          本文标题:前端文件上传方式

          本文链接:https://www.haomeiwen.com/subject/rwqoqctx.html