FILE API实现文件上传

why?为什么要做文件上传?

业务需要,浏览器上传文件也是做后台需要的一些操作。 虽然文件上传的方案包括: ajax 富客户端编程 websocket 但是哪种方式都需要对文件进行解析,解析形成二进制文件,只是传输形成的二进制文件的方式不同。 而且在ajax内部也是存在不同的发送数据的方式

how?实现文件上传的原理?

File 对象是来自用户在一个 元素上选择文件后返回的 FileList 对象.

what?做什么?

在聊做什么之前,首先聊聊,能不能做




axios文件上传Network Error 上传文件api_如何实现文件加密上传


浏览器对FileApi的兼容性

再聊聊,做什么?

  1. 浏览器实现上传文件的核心即FILE API对浏览器的兼容性也是一个必须面对的问题,所幸chrome是支持的,对于后台项目来说也是OK的,移动端的浏览器支持也不错。很不幸的是IE,因为历史原因导致IE不得不使用activeX之类的东西的打补丁了。
  2. 那么?show me the code
  3. ajax当中使用formdata的时候
https://developer.mozilla.org/zh-CN/docs/Web/API/FormData/Using_FormData_Objects


  • ajax使用 enctype="multipart/form-data" html
<body>
    <h1>File API Demo</h1>
    <div>
        <form enctype="multipart/form-data" onclick="uploadAndSubmit()">
            <p>Upload File:
                <input type="file" name="file" />
            </p>
            <p>
                <input type="submit" value="Submit" />
            </p>
        </form>
        <div>Progessing (in Bytes):
            <span id="bytesRead"></span> /
            <span id="bytesTotal"></span>
        </div>
    </div>
</body>


js代码


function uploadAndSubmit() {
            var form = document.forms["demoForm"];

            if (form["file"].files.length > 0) {
                var file = form["file"].files[0];
                // try sending
                var reader = new FileReader();
                reader.onloadstart = function () {
                    console.log("onloadstart");
                    document.getElementById("bytesTotal").textContent = file.size;
                }
                reader.onprogress = function (p) {
                    console.log("onprogress");
                    document.getElementById("bytesRead").textContent = p.loaded;
                }
                reader.onload = function () {
                    console.log("load complete");
                }
                reader.onloadend = function () {
                    if (reader.error) {
                        console.log(reader.error);
                    } else {
                        document.getElementById("bytesRead").textContent = file.size;
                        var xhr = new XMLHttpRequest();
                        xhr.open( 
                        /* method */ "POST",
                         /* target url */ "upload?fileName=" + file.name /*,);
                        xhr.overrideMimeType("application/octet-stream");
                        xhr.sendAsBinary(reader.result);

                        xhr.onreadystatechange = function () {
                            if (xhr.readyState == 4) {
                                if (xhr.status == 200) {
                                    console.log("upload complete");
                                    console.log("response: " + xhr.responseText);
                                }
                            }
                        }
                    }

                }
                reader.readAsBinaryString(file);
            } else {
                alert("Please choose a file.");
            }
        }


上面的代码写的比较粗糙,可以当做伪代码阅读(虽然也能跑)

聊聊代码前置的东西

类型 FileList 包含一组 File 对象。通常 FileList 对象可以从表单中的文件域中拿取。Blob 对象代表浏览器所能读取的一组原始二进制流。Blob 对象中,属性 size 表示流的大小。函数 slice() 可以将一个长的 Blob 对象分割成小块。File 对象继承自 Blob 对象,在 Blob 对象基础上增加了和 File 相关的属性。其中,属性 name 表示文件的名字,这个名字去掉了文件的路径信息,而只保留了文件名。属性 type 表示文件的 MIME 类型。属性 urn 则代表这个文件的 URN 信息。为完成文件读取的操作,一个 FileReader 对象实例会关联 File 或 Blob 对象,并提供三种不同的文件读取函数以及 6 种事件。
文件读取函数

  1. readAsBinaryString() 读取文件内容,读取结果作为一个binary String(),文件的每一个byte会被表示为一个【0,255】区间内的整数,函数接受一个file对象组作为参数
    具体的代码类似于
var reader = new FileReader();
reader.readAsBinaryString(file);


  1. readAsText() 读取文件内容,读取结果为一串代表文件内容的文本,函数接受一个File对象,以及文本编码名称作为参数
    代码看起来类似这样
var reader = new FileReader()
reader.readAsText(file,'utf8') //读取文件内容


  1. readAsDataURL
    读取文件内容,读取文件内容,读取结果为一个 data: 的 URL。
    Data URLs,即前缀为 data: 协议的的URL,其允许内容创建者向文档中嵌入小文件。
    Data URLs由四个部分组成data:[<mediatype>][;base64],<data>mediatype 是个 MIME 类型的字符串,例如 "image/jpeg" 表示 JPEG 图像文件。如果被省略,则默认值为 text/plain;charset=US-ASCII

聊聊fileReader对象实例的文件读取事件相关的函数

  1. Onloadstart 文件读取开始时触发。
    Progress 当读取进行中时定时触发。事件参数中会含有已读取总数据量。
    Abort 当读取被中止时触发。
    Error 当读取出错时触发。
    Load 当读取成功完成时触发。
    Loadend 当读取完成时,无论成功或者失败都会触发。
    所以这些钩子函数类似fileReader对象实例的声明周期