實現拖拽上傳功能, 學到的技術點總結

完成託拽上傳功能學到的技術點

1、拖拽獲取到文件 a). 原理調用原生js提供的 drop系列的事件html

  1. dragentetr 當被鼠標拖動的對象進入其容器範圍內時觸發此事件
  2. dragleave 當被鼠標拖動的對象離開其容器範圍內時觸發此事件
  3. drop 當被鼠標拖動的對象在容器範圍內時被放下時觸發此事件
  4. dragover 當某被拖動的對象在另外一對象容器範圍內拖動時觸發此事件 使用時須要給body綁定以上四個事件, 取消瀏覽器的默認行爲(打開文件);
function clearDefault (event) {
    var e = event || window.event
    e.preventDefault()
  }
  document.addEventListener('dragentetr', clearDefault)
  document.addEventListener('dragleave', clearDefault)
  document.addEventListener('drop', clearDefault)
  document.addEventListener('dragover', clearDefault)

b). 在dom上指定一個區域做爲咱們要拖入文件的區域。通常是一個div;jquery

<div id="dropBox"></div>

爲改div綁定上事件,web

  1. dragenter 進入事件, 提示用戶能夠放開鼠標
  2. dragleave 離開區域時, 提示文字恢復爲將文件拖至此區域
  3. drop 文件進入此區域時, 能夠經過e.dataTransfer.files 這個數組訪問到進入次區域的全部文件, 是一個索引數組;能夠訪問到文件的一些信息
var div = document.querySelector('#dropBox')
  div.addEventListener('dragenter', function (event) {
    var e = event || window.event
    e.preventDefault()
    this.innerHTML = '請釋放鼠標'
    this.style.borderColor = 'green'
  })
  div.addEventListener('dragleave', function (event) {
    var e = event || window.event
    e.preventDefault()
    this.style.borderColor = 'red'
    this.innerHTML = '請將文件拖在此區域'
  })
  div.addEventListener('drop', function (event) {
    var e = event || window.event
    e.preventDefault()
    var files = e.dataTransfer.files // 這個是一個索引數組 => [file1, file2]
    // 每一個file擁有如下信息 注意: 它們都是隻讀的
    var file = {
      lastModified: 1500618905073,   // =>這個表明是最後修改時間 格式是時間戳
      lastModifiedDate: 'Fri Jul 21 2017 14:35:05 GMT+0800 (中國標準時間)',  // =>一樣也是最後修改的時間 格式是Date形式
      name: '測試文檔.docx', // =>文件的名字
      size: 969331,  // =>文件的大小 單位是B 若有須要的話, 須要換算爲別的單位
      type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', // =>文件的類型
      webkitRelativePath: ''// => MDN上面說 它返回 File 相關的 path 或 URL。
    }
    // 這裏咱們只是單文件上傳, 只取files中第一個文件
    file = files[0]
    // 獲取文件的路徑採用的是另一個方法 window.URL.createObjectURL(file) 它的做用是建立一個能夠被瀏覽器識別的路徑 是一個網絡地址形式的路徑信息
    var filePath = window.URL.createObjectURL(file)
    // 根據上面說的咱們在控制檯打印文件的信息
    console.log('文件名: ' + file.name)
    console.log('大小: ' + bytesToSize(file.size))
    console.log('類型: ' + file.type)
    console.log('路徑: ' + filePath)
    /*
     *到這裏已經獲取到了文件, 可使用ajax
     *上傳到服務器, 也可使用H5的
     *FileReader
     *讀取它的內容
     */
  })
  /*
   *在網上找的換算字節的函數
   *參數: bytes number 待轉換的數字
   *輸出: 合理的計算後並輸出單位 B KB MB...
   */
  function bytesToSize (bytes) {
    if (bytes === 0) return '0 B'
    var k = 1000 // or 1024
    var sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
    var i = Math.floor(Math.log(bytes) / Math.log(k))
    return (bytes / Math.pow(k, i)).toPrecision(3) + ' ' + sizes[i]
  }

2、XMLHttpRequest Level 2 XMLHttpRequest Level 2 我喜歡叫它ajax2代 它與第一代相比增長了不少實用的東西這裏不作詳細說明ajax

  1. 跨域訪問, 在後端加上跨域響應頭 響應頭代碼: Access-Control-Allow-Origin: "你本身的域名" ps這篇文章再也不作詳細的說明
  2. 能夠獲取服務器端的二進制數據。範例代碼: xhr.responseType = 'blob' ; ps這個我也不是很理解, 暫時作爲記錄
  3. 能夠獲取數據傳輸的進度信息。待會下面會詳細說明這個。
  4. timeout 屬性, 等待必定時間之後,請求未結束, 會觸發ontimeout 事件, 認爲這次請求超時, 失敗。
  5. FormData 屬性 本身在js中建立form形式的數據, 而不用像之前那樣在html中建立一個不顯示的form。待會下面會詳細說明這個。 還有不少別的功能, 我會慢慢的補充...
// 建立一個ajax對象
  var xhr = new XMLHttpRequest()
  xhr.open('GET', 'test.do')
  xhr.send()

獲取數據傳輸進度信息 上傳於下載調用的是不用對象的onprogress事件 上傳觸發的是xhr.upload對象的 onprogress事件 下載觸發的是xhr對象的onprogress事件chrome

xhr.onprogress = updateProgress
  xhr.upload.onprogress = updateProgress
  function updateProgress (event) {
    if (event.lengthComputable) {
      // event.loaded  已經發送 / 下載的數據量
      // event.total 文件的總數據量
      var completedPercent = event.loaded / event.total
      console.log(completedPercent)
    }
  }
/*
   * 還有一些對應的事件, 這裏只提一下
   * load事件:傳輸成功完成。
   * abort事件:傳輸被用戶取消。
   * error事件:傳輸中出現錯誤。
   * loadstart事件:傳輸開始。
   * loadEnd事件:傳輸結束,可是不知道成功仍是失敗。
   */

timeout 請求超時的相關設置json

xhr.timeout = 5000 // 單位ms
  xhr.ontimeout = function () { // 請求發起後的5s內爲完成 就會結束請求並觸發該事件
    console.log('請求錯誤')
  }

3、FormData 說明 在之前咱們的開發中, 獲取一個form的input的值時 採用本身定義一個json 鍵爲與後端定義好的name, 值爲用jquery選擇器找到對應的input,用val()方法獲取值。 如今有了FormData之後咱們不須要用jquery去獲取一個input的val()值, 像下面這樣: 在html中寫一個form表單後端

<form id="submit" action="http://test">
  <input type="text" name="username">
  <input type="text" name="pwd">
  <input type="submit" value="提交">
</form>

在js中咱們這樣寫跨域

var submit = document.querySelector('#submit') // 獲取到id是submit的表單
  submit.onsubmit = function () {
    var data = new FormData(submit) // 初始化一個formdata對象
    /*
     * 這裏咱們已經獲取到了id爲submit中全部input的值
     * 此時咱們console.log(data)的話在控制檯只能看到一個空對象。
     * 這裏咱們用ajax發起請求的時候,在chrome的控制檯的network選項卡中能夠看到它內部的東西
     */
    // 若是須要在data中臨時加一個值的時候能夠這樣的形式加入
    // data.append('name', 'value')
    data.append('enail', '345565@qq.com')
  }

如今就能夠上傳我在上邊拖拽拿到的文件了數組

function ajaxPushFile (file) {
    // 這裏的file就是上面咱們獲取到的file
    if (!file) {
      return false
    }
    var data = new FormData() // 初始化一個formdata對象 這裏沒有from元素就不傳值
    data.append('files', file) // 將文件加入formdata中
    var xhr = new XMLHttpRequest() // 初始化ajax
    xhr.open('POST', 'http://test')
    xhr.timeout = 10000 // 設置超時
    xhr.responseType = 'text' // 設置響應返回的數據格式
    xhr.onreadystatechange = function (e) {
      if (this.readyState === 4 && this.status === 200) {
        // 獲取返回的值
      }
    }
    xhr.ontimeout = function () { // 超時的回調
      alert('上傳失敗')
    }
    xhr.upload.onprogress = updateProgress // 獲取上傳進度
    function updateProgress (event) {
      if (event.lengthComputable) {
        // event.loaded  已經發送 / 下載的數據量
        // event.total 文件的總數據量
        var completedPercent = event.loaded / event.total
        console.log(completedPercent)
      }
    }

    xhr.send(data)
  }

到此 拖拽功能完成 這個功能用到了拖拽事件 與 ajax2 與 FormData 技術點瀏覽器

頁面所有代碼:

<!doctype html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<style>
* {
    margin: 0;
    padding: 0;
}

#drop {
    width: 500px;
    height: 400px;
    border: 10px dotted red;
}
</style>

<body>
    <div id="drop">
        請將文件拖拽到這裏
    </div>
</body>
<script>
function clearDefault(event) {
    var e = event || window.event
    e.preventDefault()
}
document.addEventListener('dragentetr', clearDefault)
document.addEventListener('dragleave', clearDefault)
document.addEventListener('drop', clearDefault)
document.addEventListener('dragover', clearDefault)
var div = document.querySelector('#drop')
div.addEventListener('dragenter', function(event) {
    var e = event || window.event
    e.preventDefault()
    this.innerHTML = '請釋放鼠標'
    this.style.borderColor = 'green'
})
div.addEventListener('dragleave', function(event) {
    var e = event || window.event
    e.preventDefault()
    this.style.borderColor = 'red'
    this.innerHTML = '請將文件拖在此區域'
})
div.addEventListener('drop', function(event) {
        var e = event || window.event
        e.preventDefault()
        var files = e.dataTransfer.files // 這個是一個索引數組 => [file1, file2]
            // 每一個file擁有如下信息 注意: 它們都是隻讀的
        var file = {
                lastModified: 1500618905073, // =>這個表明是最後修改時間 格式是時間戳
                lastModifiedDate: 'Fri Jul 21 2017 14:35:05 GMT+0800 (中國標準時間)', // =>一樣也是最後修改的時間 格式是Date形式
                name: '測試文檔.docx', // =>文件的名字
                size: 969331, // =>文件的大小 單位是B 若有須要的話, 須要換算爲別的單位
                type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', // =>文件的類型
                webkitRelativePath: '' // => MDN上面說 它返回 File 相關的 path 或 URL。
            }
            // 這裏咱們只是單文件上傳, 只取files中第一個文件
        file = files[0]
            // 獲取文件的路徑採用的是另一個方法 window.URL.createObjectURL(file) 它的做用是建立一個能夠被瀏覽器識別的路徑 是一個網絡地址形式的路徑信息
        var filePath = window.URL.createObjectURL(file)
            // 根據上面說的咱們在控制檯打印文件的信息
        console.log('文件名: ' + file.name)
        console.log('大小: ' + bytesToSize(file.size))
        console.log('類型: ' + file.type)
        console.log('路徑: ' + filePath)
            /*
             *到這裏已經獲取到了文件, 可使用ajax
             *上傳到服務器, 也可使用H5的
             *FileReader
             *讀取它的內容
             */
    })
    /*
     *在網上找的換算字節的函數
     *參數: bytes number 待轉換的數字
     *輸出: 合理的計算後並輸出單位 B KB MB...
     */
function bytesToSize(bytes) {
    if (bytes === 0) return '0 B'
    var k = 1000 // or 1024
    var sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
    var i = Math.floor(Math.log(bytes) / Math.log(k))
    return (bytes / Math.pow(k, i)).toPrecision(3) + ' ' + sizes[i]
}
function ajaxPushFile (file) {
    // 這裏的file就是上面咱們獲取到的file
    if (!file) {
      return false
    }
    var data = new FormData() // 初始化一個formdata對象 這裏沒有from元素就不傳值
    data.append('files', file) // 將文件加入formdata中
    var xhr = new XMLHttpRequest() // 初始化ajax
    xhr.open('POST', 'http://test')
    xhr.timeout = 10000 // 設置超時
    xhr.responseType = 'text' // 設置響應返回的數據格式
    xhr.onreadystatechange = function (e) {
      if (this.readyState === 4 && this.status === 200) {
        // 獲取返回的值
      }
    }
    xhr.ontimeout = function () { // 超時的回調
      alert('上傳失敗')
    }
    xhr.upload.onprogress = updateProgress // 獲取上傳進度
    function updateProgress (event) {
      if (event.lengthComputable) {
        // event.loaded  已經發送 / 下載的數據量
        // event.total 文件的總數據量
        var completedPercent = event.loaded / event.total
        console.log(completedPercent)
        div.innerHTML = '已完成: ' + (completedPercent * 100) + '%'
      }
    }
    xhr.send(data)
  }
</script>

</html>
相關文章
相關標籤/搜索