mozilla
您的搜尋結果

    在網頁應用程式中使用本地檔案

     

    現在可以透過新增至HTML5 DOM的File API讓web內容要求使用者選取本地端的檔案後讀取被選取檔案中的內容。檔案的選取動作可以使用HTML的 input 元素,或是用拖曳檔案(drag and drop)的方式來完成。

    如果你想要使用DOM 檔案 API 的文件擴展或是其他Chrome 程式碼,你可以參考使用DOM檔案API在FireFox外觀代碼中

    使用HTML選擇本地檔案

    使用File API選擇單一檔案是非常簡單的,如下

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

    當使用者選取一個檔案 , 呼叫 handleFiles() 會的到一個 FileList 的物件。 FileList 裡面還會有一個 File 的物件,裡面的東西就是使用者選取的檔案。

    如果你想要讓使用者一次選擇多個檔案,可以在 input 元素中使用 multiple 的屬性 :

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

    在上述這個例子中,檔案名單會傳遞到 handleFiles() 函數,其中包含了使用者選的每個檔案 File 物件

    使用click() 方法隱藏檔案輸入元素

    從 Gecko 2.0 (Firefox 4 / Thunderbird 3.3 / SeaMonkey 2.1)開始,為了顯示個人化開啟檔案的UI和使用者選擇的檔案可以隱藏 <input> 元素和顯示個人化的設計可以藉由設置CSS "display:none" 和對<input> 元素呼叫 click() 方法。

    HTML 如下:

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

    doClick() 方法:

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

    很明顯,可以使用CSS裝飾開啟檔案選擇的按鈕。

    使用 EventListener 動態地監聽

    如果使用了其他的函數庫( jQuery),你會需要使用 element.addEventListener() 去監聽事件, 例如:

    var inputElement = document.getElementById("inputField");
    inputElement.addEventListener("change", handleFiles, false);
    
    function handleFiles() {
      var fileList = this.files;
    
      /* now you can work with the file list */
    }
    

    在這個例子中,handleFiles() 函數找尋檔案清單而非接收參數, 因為這樣增加的 event listeners 不能接受參數.

    Using object URLs

    (Firefox 4 / Thunderbird 3.3 / SeaMonkey 2.1)

    Gecko 2.0 (Firefox 4 / Thunderbird 3.3 / SeaMonkey 2.1) introduces support for the DOM window.URL.createObjectURL()window.URL.revokeObjectURL() 方法. 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);
    

    使用拖放選取檔案

    使用者可以使用拖放來選取檔案,首先要設置放的區域,確定文件可以接收放的檔案,方法如下:

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

    在這個範例中,我們將ID "dropbox" 設為放的區域,這是由於我們監聽了 dragenter, dragoverdrop事件.

    我們甚至不需要處理 dragenterdragover事件, 所以這些函數很簡單. They just stop propagation of the event and prevent the default action from occurring:

    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 來獲取檔案清單, 並傳遞給 handleFiles(). 我們可以發現,不論使用拖放或是其他取得檔案,處理檔案的方式都是相同.

    獲得選取檔案的資訊

    FileList 物件 provided by the DOM lists all the files selected by the user, each specified as a File object. You can determine how many files the user selected by checking the value of the file list's length attribute:

    var numFiles = files.length;
    

    Individual File objects can be retrieved by simply accessing the list as an array:

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

    This loop iterates over all the files in the file list.

    There are three attributes provided by the File object that contain useful information about the file.

    name
    The file's name as a read-only string. This is just the file name, and does not include any path information.
    size
    The size of the file in bytes as a read-only 64-bit integer.
    type
    The MIME type of the file as a read-only string, or "" if the type couldn't be determined.

    範例:顯示選取的圖片

    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. Simply establish your input element or drop zone as discussed previously, and have them call a function such as the handleFiles() function below.

    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);
      }
    }
    

    Here our loop handling the user-selected files looks at each file's type attribute to see if it's an image file (by doing a regular expression match on the string "image.*"). For each file that is an image, we create a new img element. CSS can be used to establish any pretty borders, shadows, and to specify the size of the image, so that doesn't even need to be done here.

    Each image has the CSS class "obj" added to it, to make them easy to find in the DOM tree. We also add a file attribute to each image specifying the File for the image; this will let us fetch the images for actually uploading later. Finally, we use Node.appendChild() to add the new thumbnail to the preview area of our document.

    Then we establish the FileReader to handle actually asynchronously loading the image and attaching it to the img element. After creating the new FileReader object, we set up its onload function, then call readAsDataURL() to start the read operation in the background. When the entire contents of the image file are loaded, they are converted into a data: URL, which is passed to the onload callback. Our implementation of this routine simply sets the img element's src attribute to the loaded image, which results in the image appearing in the thumbnail on the user's screen.

    Example: Using object URLs to display images

    (Firefox 4 / Thunderbird 3.3 / SeaMonkey 2.1)

    This example uses object URLs to display image thumbnails. In addition, it displays other file information including their names and sizes. You can view the example live (note that it requires a nightly build of Firefox from November 22 or later, or Firefox 4.0 beta 8).

    Note: This API existed in earlier Firefox 4 betas but changed on November 22, so be sure you're on a current build!

    The HTML that presents the interface looks like this:

    <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 above in the section Using hidden file input elements using the click() method, as is the doClick() method that invokes the file picker.

    The handleFiles() method follows:

    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 () {
            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.

    範例:上傳檔案

    Another thing you might want to do is let the user upload the selected file or files (such as the images selected using the previous example) to a server. This can be done asynchronously very easily.

    新增上傳的工作

    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.

    處理上傳檔案的程序

    The FileUpload function accepts two inputs: an image element and a file from which to read the image data.

    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.

    非同步處理上傳檔案的程序

    function fileUpload(file) {
      // Please report improvements to: marco.buratto at tiscali.it
      
      var fileName = file.name,
        fileSize = file.size,
        fileData = file.getAsBinary(), // works on TEXT data ONLY.
        boundary = "xxxxxxxxx",
        uri = "serverLogic.php",
        xhr = new XMLHttpRequest();
      
      xhr.open("POST", uri, true);
      xhr.setRequestHeader("Content-Type", "multipart/form-data, boundary="+boundary); // simulate a file MIME POST request.
      xhr.setRequestHeader("Content-Length", fileSize);
      
      xhr.onreadystatechange = function() {
        if (xhr.readyState == 4) {
          if ((xhr.status >= 200 && xhr.status <= 200) || xhr.status == 304) {
            
            if (xhr.responseText != "") {
              alert(xhr.responseText); // display response.
            }
          }
        }
      }
      
      var body = "--" + boundary + "\r\n";
      body += "Content-Disposition: form-data; name='fileId'; filename='" + fileName + "'\r\n";
      body += "Content-Type: application/octet-stream\r\n\r\n";
      body += fileData + "\r\n";
      body += "--" + boundary + "--";
      
      xhr.send(body);
      return true;
    }
    

    This needs to be modified for working with binary data, too.

    你也可以參考這些文章

    Document Tags and Contributors

    Contributors to this page: irvinfly, alk03073135, orinx, Vdragon
    最近更新: alk03073135,