mozilla
您的搜索结果

    如何在web应用程序中使用文件

    使用HTML5 DOM新增的File API,现在可以让网页要求用户选择本地文件,并且读取这些文件的信息了。选择的方式既可以是HTML<input> 元素,也可以是拖拽 

    你可以在chrome扩展等代码中使用DOM File API ;事实上有些需要注意的额外特性。参考 Using the DOM File API in chrome code .

    访问选中的文件

    考虑下面的HTML:

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

    通过File API,我们可以在用户选取一个或者多个文件之后,访问到代表了所选文件的一个或多个File对象,这些对象被包含在一个FileList对象中.

    如果用户只选择了一个文件,那么我们只需要访问这个FileList对象中的第一个元素.

    可以使用传统的DOM选择方法来获取到用户所选择的文件:

    var selected_file = document.getElementById('input').files[0];

    还可以使用jQuery选择器来选择:

    var selected_file = $('#file').get(0).files[0];

    在change事件发生时读取所选择的文件

    另外,还可以在input元素上的change事件触发时再访问它的files属性:

    <input type="file" id="input" onchange="handleFiles(this.files)">

    当用户成功选取若干个文件后,handleFiles()函数会被调用,且一个包含了用户所选文件的FileList对象会作为参数传入该函数.

    如果你的程序可以让用户选择多个文件,记得要在input元素上加上multiple属性:

    <input type="file" id="input" multiple onchange="handleFiles(this.files)">

    这样的话,如果用户真的选择了多个文件,那么传入handleFiles()函数的文件列表将会包含多个File对象,每个File对象对应一个真实的文件.

    动态添加change事件监听器

    你还可以通过element.addEventListener()方法来添加多个change事件处理函数,像这样:

    var inputElement = document.getElementById("inputField");
    inputElement.addEventListener("change", handleFiles, false);
    function handleFiles() {
      var fileList = this.files; 
    }

    获取所选文件的信息

    用户所选择的文件都存储在了一个FileList对象上,其中每个文件都对应了一个File对象.你可以通过这个FileList对象的length属性知道用户一共选择了多少个文件:

    var numFiles = files.length;

    可以通过普通的循环语句来操作每个单独的File对象:

    for (var i = 0, numFiles = files.length; i < numFiles; i++) {
      var file = files[i];
      ..
    }
    

    File对象上有三个属性提供了所包含文件的相关信息.

    name
    文件名,只读字符串,不包含任何路径信息.
    size
    文件大小,单位为字节,只读的64位整数.
    type
    MIME类型,只读字符串,如果类型未知,则返回空字符串.

    例子:显示文件大小

    下面的例子演示了size属性的用法:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>File(s) size</title>
    <script>
    function updateSize() {
      var nBytes = 0,
          oFiles = document.getElementById("uploadInput").files,
          nFiles = oFiles.length;
      for (var nFileId = 0; nFileId < nFiles; nFileId++) {
        nBytes += oFiles[nFileId].size;
      }
      var sOutput = nBytes + " bytes";
      // optional code for multiples approximation
      for (var aMultiples = ["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"], nMultiple = 0, nApprox = nBytes / 1024; nApprox > 1; nApprox /= 1024, nMultiple++) {
        sOutput = nApprox.toFixed(3) + " " + aMultiples[nMultiple] + " (" + nBytes + " bytes)";
      }
      // end of optional code
      document.getElementById("fileNum").innerHTML = nFiles;
      document.getElementById("fileSize").innerHTML = sOutput;
    }
    </script>
    </head>
    
    <body onload="updateSize();">
    <form name="uploadForm">
    <p><input id="uploadInput" type="file" name="myFiles" onchange="updateSize();" multiple> selected files: <span id="fileNum">0</span>; total size: <span id="fileSize">0</span></p>
    <p><input type="submit" value="Send file"></p>
    </form>
    </body>
    </html>
    

    在隐藏的文件输入框上调用click()方法

    从Gecko 2.0 (Firefox 4 / Thunderbird 3.3 / SeaMonkey 2.1)开始,你可以隐藏掉默认的文件输入框<input>元素,使用自定义的界面来充当打开文件选择对话框的按钮.实现起来很简单,你只需要使用样式display:none把原本的文件输入框隐藏掉,然后在需要的时候调用它的click()方法就行了.

    考虑一下下面的HTML:

    <input type="file" id="fileElem" multiple accept="image/*" style="display:none" onchange="handleFiles(this.files)">
    <a href="#" id="fileSelect">Select some files</a>

    为自定义的按钮绑定click事件:

    var fileSelect = document.getElementById("fileSelect"),
      fileElem = document.getElementById("fileElem");
    
    fileSelect.addEventListener("click", function (e) {
      if (fileElem) {
        fileElem.click();
      }
      e.preventDefault(); // prevent navigation to "#"
    }, false);
    

    这样,你就能任意改变这个新按钮的样式了.

    通过拖放操作选择文件

    你可以让用户将本地文件拖放到你的应用程序上.

    首先要创建一个拖放操作的目的区域:

    var dropbox;
    
    dropbox = document.getElementById("dropbox");
    dropbox.addEventListener("dragenter", dragenter, false);
    dropbox.addEventListener("dragover", dragover, false);
    dropbox.addEventListener("drop", drop, false);
    

    在这个例子中,ID为dropbox的元素所在的区域是我们的拖放目的区域.我们需要在该元素上绑定dragenter, dragover,和drop事件.

    我们必须阻止dragenterdragover事件的默认行为,这样才能触发drop事件:

    function dragenter(e) {
      e.stopPropagation();
      e.preventDefault();
    }
    
    function dragover(e) {
      e.stopPropagation();
      e.preventDefault();
    } 
    

    下面是drop()函数:

    function drop(e) {
      e.stopPropagation();
      e.preventDefault();
    
      var dt = e.dataTransfer;
      var files = dt.files;
    
      handleFiles(files);
    }
    

    在该函数中,我们从事件对象中获取到dataTransfer对象,把该对象包含的Filelist对象传入函数handleFiles(),这个函数会无区别的对待从input元素或拖放操作中来的文件列表.

    例子:显示用户所选图片的缩略图

    Let's say you're developing the next great photo-sharing web site, and want to use HTML5 to display thumbnail previews of images before the user actually uploads them. You can establish your input element or drop zone as discussed previously, and have them call a function such as the handleFiles() function below.

    假设你正在开发下一个伟大的照片分享网站,并希望使用HTML5在用户上传他们图片之前进行缩略图预览。您可以如前面所讨论的建立一个输入元素或者拖放区域,并调用一个函数,如下面的handleFiles()函数。

    function handleFiles(files) {
      for (var i = 0; i < files.length; i++) {
        var file = files[i];
        var imageType = /image.*/;
        
        if (!file.type.match(imageType)) {
          continue;
        }
        
        var img = document.createElement("img");
        img.classList.add("obj");
        img.file = file;
        preview.appendChild(img);
        
        var reader = new FileReader();
        reader.onload = (function(aImg) { return function(e) { aImg.src = e.target.result; }; })(img);
        reader.readAsDataURL(file);
      }
    }

    这里我们循环处理用户选择的文件,查看每个文件的类型属性,看看这是否是一个图像文件(通过一个正则表达式匹配字符串“image.*”)。对于每个图片文件,我们创建一个新的img元素。CSS可以用于建立任何漂亮的边界,阴影,和指定图像的大小,所以,甚至不需要在这里完成。

    每张图片我们添加一个obj类,让他们更容易的在DOM树中被找到。我们也在图片上添加了一个file属性来确认每张图片的 File,这样可以帮助我们在之后真正的上传工作时获取到图片。最后我们使用 Node.appendChild() 把缩略图添加到我们先前的文档区域中

    然后,我们建立了{ { domxref(FileReader)} }来处理图片的异步加载,并把它添加到img元素上。在创建新的FileReader对象之后,我们建立了onload函数,然后调用readAsDataURL()开始在后台进行读取操作。当图像文件的所有内容加载后,他们转换成一个data:URL,传递到onload回调函数中。之后只需要把img元素的src属性设置为这个加载过的图像,就可以让图像的缩略图出现在用户的屏幕上。

    使用对象URL

    Gecko 2.0 (Firefox 4 / Thunderbird 3.3 / SeaMonkey 2.1)开始支持window.URL.createObjectURL()window.URL.revokeObjectURL()两个DOM方法.These let you create simple URL strings that can be used to reference any data that can be referred to using a DOM File object, including local files on the user's computer.

    When you have a File object you'd like to reference by URL from HTML, you can create an object URL for it like this:

    var objectURL = window.URL.createObjectURL(fileObj);

    The object URL is a string identifying the File object. Each time you call window.URL.createObjectURL(), a unique object URL is created, even if you've created an object URL for that file already. Each of these must be released. While they are released automatically when the document is unloaded, if your page uses them dynamically, you should release them explicitly by calling window.URL.revokeObjectURL():

    window.URL.revokeObjectURL(objectURL);

    例子: 使用对象URL来显示图片

    这个例子使用了对象URL来显示图片缩略图,同时还显示了图片的其他信息,包括图片名和图片大小,你可以查看该例子的在线演示.

    负责界面呈现的HTML如下:

    <input type="file" id="fileElem" multiple accept="image/*" style="display:none" onchange="handleFiles(this.files)">
    <a href="#" id="fileSelect">Select some files</a> 
    <div id="fileList">
      <p>No files selected!</p>
    </div>
    

    This establishes our file <input> element, as well as a link that invokes the file picker, since we keep the file input hidden to prevent that less-than-attractive UI from being displayed. This is explained in the section Using hidden file input elements using the click() method, as is the method that invokes the file picker.

    The handleFiles() method follows:

    window.URL = window.URL || window.webkitURL;
    
    var fileSelect = document.getElementById("fileSelect"),
        fileElem = document.getElementById("fileElem"),
        fileList = document.getElementById("fileList");
    
    fileSelect.addEventListener("click", function (e) {
      if (fileElem) {
        fileElem.click();
      }
      e.preventDefault(); // prevent navigation to "#"
    }, false);
    
    function handleFiles(files) {
      if (!files.length) {
        fileList.innerHTML = "<p>No files selected!</p>";
      } else {
        var list = document.createElement("ul");
        for (var i = 0; i < files.length; i++) {
          var li = document.createElement("li");
          list.appendChild(li);
          
          var img = document.createElement("img");
          img.src = window.URL.createObjectURL(files[i]);
          img.height = 60;
          img.onload = function(e) {
            window.URL.revokeObjectURL(this.src);
          }
          li.appendChild(img);
          
          var info = document.createElement("span");
          info.innerHTML = files[i].name + ": " + files[i].size + " bytes";
          li.appendChild(info);
        }
        fileList.appendChild(list);
      }
    }
    

    This starts by fetching the URL of the <div> with the ID fileList. This is the block into which we'll insert out file list, including thumbmails.

    If the FileList object passed to handleFiles() is null, we simply set the inner HTML of the block to display "No files selected!". Otherwise, we start building our file list, as follows:

    1. A new unordered list (<ul>) element is created.
    2. The new list element is inserted into the <div> block by calling its element.appendChild() method.
    3. For each File in the FileList represented by files:
      1. Create a new list item (<li>) element and insert it into the list.
      2. Create a new image (<img>) element.
      3. Set the image's source to a new object URL representing the file, using window.URL.createObjectURL() to create the blob URL.
      4. Set the image's height to 60 pixels.
      5. Set up the image's load event handler to release the object URL, since it's no longer needed once the image has been loaded. This is done by calling the window.URL.revokeObjectURL() method, passing in the object URL string as specified by img.src.
      6. Append the new list item to the list.

    例子:上传用户选择的文件

    你可以异步的将用户所选择的文件上传到服务器上(比如一张图片).

    创建上传任务

    Continuing with the code that builds the thumbnails in the previous example, recall that every thumbnail image is in the CSS class obj, with the corresponding File attached in a file attribute. This lets us very easily select all the images the user has chosen for uploading using Document.querySelectorAll(), like this:

    function sendFiles() {
      var imgs = document.querySelectorAll(".obj");
      
      for (var i = 0; i < imgs.length; i++) {
        new FileUpload(imgs[i], imgs[i].file);
      }
    }
    

    Line 2 creates an array, called imgs, of all the elements in the document with the CSS class obj. In our case, these will be all the image thumbnails. Once we have that list, it's trivial to go through the list, creating a new FileUpload instance for each. Each of these handles uploading the corresponding file.

    实现文件上传

    FileUpload函数接受两个参数:一个IMG元素,一个File对象或Blob对象.

    function FileUpload(img, file) {
      var reader = new FileReader();  
      this.ctrl = createThrobber(img);
      var xhr = new XMLHttpRequest();
      this.xhr = xhr;
      
      var self = this;
      this.xhr.upload.addEventListener("progress", function(e) {
            if (e.lengthComputable) {
              var percentage = Math.round((e.loaded * 100) / e.total);
              self.ctrl.update(percentage);
            }
          }, false);
      
      xhr.upload.addEventListener("load", function(e){
              self.ctrl.update(100);
              var canvas = self.ctrl.ctx.canvas;
              canvas.parentNode.removeChild(canvas);
          }, false);
      xhr.open("POST", "http://demos.hacks.mozilla.org/paul/demos/resources/webservices/devnull.php");
      xhr.overrideMimeType('text/plain; charset=x-user-defined-binary');
      reader.onload = function(evt) {
        xhr.sendAsBinary(evt.target.result);
      };
      reader.readAsBinaryString(file);
    }
    

    The FileUpload() function shown above creates a throbber, which is used to display progress information, then creates an XMLHttpRequest to handle uploading the data.

    Before actually transferring the data, several preparatory steps are taken:

    1. The XMLHttpRequest's upload progress listener is set to update the throbber with new percentage information, so that as the upload progresses, the throbber will be updated based on the latest information.
    2. The XMLHttpRequest's upload load event handler is set to update the throbber with 100% as the progress information (to ensure the progress indicator actually reaches 100%, in case of granularity quirks during the process). It then removes the throbber, since it's no longer needed. This causes the throbber to disappear once the upload is complete.
    3. The request to upload the image file is opened by calling XMLHttpRequest's open() method to start generating a POST request.
    4. The MIME type for the upload is set by calling the XMLHttpRequest function overrideMimeType(). In this case, we're using a generic MIME type; you may or may not need to set the MIME type at all, depending on your use case.
    5. The FileReader object is used to convert the file to a binary string.
    6. Finally, when the content is loaded the XMLHttpRequest function sendAsBinary() is called to upload the file's content.

    异步实现文件上传

    <?php
    if (isset($_FILES['myFile'])) {
        // Example:
        move_uploaded_file($_FILES['myFile']['tmp_name'], "uploads/" . $_FILES['myFile']['name']);
        exit;
    }
    ?><!DOCTYPE html>
    <html>
    <head>
        <title>dnd binary upload</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <script type="text/javascript">
            function sendFile(file) {
                var uri = "/index.php";
                var xhr = new XMLHttpRequest();
                var fd = new FormData();
                
                xhr.open("POST", uri, true);
                xhr.onreadystatechange = function() {
                    if (xhr.readyState == 4 && xhr.status == 200) {
                        // Handle response.
                        alert(xhr.responseText); // handle response.
                    }
                };
                fd.append('myFile', file);
                // Initiate a multipart/form-data upload
                xhr.send(fd);
            }
    
            window.onload = function() {
                var dropzone = document.getElementById("dropzone");
                dropzone.ondragover = dropzone.ondragenter = function(event) {
                    event.stopPropagation();
                    event.preventDefault();
                }
        
                dropzone.ondrop = function(event) {
                    event.stopPropagation();
                    event.preventDefault();
    
                    var filesArray = event.dataTransfer.files;
                    for (var i=0; i<filesArray.length; i++) {
                        sendFile(filesArray[i]);
                    }
                }
        </script>
    </head>
    <body>
        <div>
            <div id="dropzone" style="margin:30px; width:500px; height:300px; border:1px dotted grey;">Drag & drop your file here...</div>
        </div>
    </body>
    </html>
    

    规范

    相关链接

    文档标签和贡献者

    此页面的贡献者有: ziyunfei, Leo_Yao, jtyjty99999
    最后编辑者: Leo_Yao,