欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

基于JavaScript實現(xiàn)文件秒傳功能

 更新時間:2024年01月08日 08:28:46   作者:碼窩醬  
在互聯(lián)網(wǎng)高速發(fā)展的今天,文件上傳已經(jīng)成為網(wǎng)頁應用中的一個基本功能,隨著用戶上傳文件尺寸的不斷增大、對質(zhì)量清晰度的要求也越來越高,所以本文給大家介紹了如何使用JavaScript實現(xiàn)文件秒傳功能,需要的朋友可以參考下

背景

上傳一個100MB的視頻文件,只需要1~3秒,是真的嗎?靠譜嗎?

此前,經(jīng)常有用戶反饋在正常網(wǎng)絡下上傳一個1GB的視頻大約需要10分鐘,我們也只能回復:“其實這種情況和上傳的時間、網(wǎng)絡以及文件大小有關(guān)”。

在互聯(lián)網(wǎng)高速發(fā)展的今天,文件上傳已經(jīng)成為網(wǎng)頁應用中的一個基本功能。隨著用戶上傳文件尺寸的不斷增大、對質(zhì)量清晰度的要求也越來越高。如何提高上傳速度、優(yōu)化用戶體驗成為了前端開發(fā)者必須面對的問題。

在此之前,最常見的優(yōu)化方案就是分塊上傳、斷點續(xù)傳,在用戶因異常斷開上傳 或 刷新頁面后,能繼續(xù)在上一次的基礎上繼續(xù)上傳。這的確能較好的提升用戶上傳體驗,也是很有必要的優(yōu)化手段,但無法實現(xiàn)文件秒傳。

什么是文件秒傳?

文件秒傳指的是當用戶上傳文件時,如果服務器已存在完全相同的文件,那么無需用戶再次上傳,直接使用服務器上的文件副本,實現(xiàn)瞬間完成上傳的過程。這種技術(shù)可以顯著減少不必要的數(shù)據(jù)傳輸,節(jié)省時間和帶寬資源。(服務器會根據(jù)有無hash的情況返回3種狀態(tài),下面會有詳細說明)

文件秒傳的原理

文件秒傳的核心原理是“文件指紋”。即文件唯一ID,通常是指文件的哈希值(如MD5、SHA-1等),它是通過哈希算法計算得出的一串固定長度的字符串,可以唯一標識文件的內(nèi)容。即使文件非常龐大,其哈希值也能迅速計算出來,并且即便只是文件中的一個字節(jié)發(fā)生變化,所得到的哈希值也會完全不同。

秒傳的三種狀態(tài)處理說明

三種狀態(tài)都需要將前端計算得出的文件hash傳遞給服務端查詢獲得

狀態(tài)一(notHash):文件在服務器不存在
此時正常分塊上傳,上傳結(jié)束后返回上傳結(jié)果

狀態(tài)二(hasHash):文件在服務器存在
根據(jù)文件hash查詢到上傳結(jié)果,直接返回(實現(xiàn)秒傳)

狀態(tài)三(hashIng):新文件第一次上傳完,但后端任務未完成, 而該文件在前端又被上傳。此時輪詢后端接口,等待后端任務完成后直接上傳結(jié)果(該文件第二次或后續(xù)上傳均已實現(xiàn)秒傳)

狀態(tài)三中說的后端任務主要是:新文件上傳完后,后端并不會直接拿前端的hash存到數(shù)據(jù)庫,而是會自己在服務端根據(jù)上傳完的視頻生成hash(生成hash規(guī)則和前端一樣)再和前端比對,以確保數(shù)據(jù)的準確性及唯一性。

如何在前端頁面實現(xiàn)文件秒傳?

關(guān)鍵技術(shù)點

  • 文件分塊hash計算
  • 拿得到的hash到后端查詢文件狀態(tài)(確定文件是否在服務端存在)
  • 根據(jù)服務端返回的上傳狀態(tài),處理上傳。

1. 計算文件hash

計算hash的方法封裝,使用md5會有相對較大的概率出現(xiàn)重復hash,建議至少使用sha1的方式計算。

/**
 * @description: 分塊計算文件hash
 * @param {*} file 文件對象
 * @param {*} chunkSize 分塊計算的文件大小,默認10MB
 * @return {*}
 */
export function calculateSliceFileHash({ file, chunkSize = 10 * 1024 * 1024 }) {
  let currentChunkIndex = 0;
  const maxChunkCount = Math.ceil(file.size / chunkSize);
  let sha1WordArray = CryptoJS.algo.SHA1.create();
  const startTime = Date.now()
  return new Promise((resolve, reject) => {
    function loadNextChunk() {
      const start = currentChunkIndex * chunkSize;
      const end = Math.min(start + chunkSize, file.size);
      const reader = new FileReader();
      reader.onload = function (e) {
        const arrayBuffer = e.target.result;
        const wordArray = CryptoJS.lib.WordArray.create(arrayBuffer);
        sha1WordArray.update(wordArray);
        const diffTime = Date.now() - startTime
        if (currentChunkIndex < maxChunkCount - 1) {
          currentChunkIndex++;
          loadNextChunk()
        } else {
          const sha1 = sha1WordArray.finalize().toString(CryptoJS.enc.Hex); // CryptoJS.enc.Hex
          resolve({ sha1, diffTime }); // 返回計算出的hash值
        }
      };
      reader.onerror = function (error) {
        console.error('Error reading file chunk:', error);
        reject({ error: parseError(error) }); // 處理錯誤
      };
      const blobSlice = file.slice(start, end);
      reader.readAsArrayBuffer(blobSlice);
    }
    loadNextChunk();
  })
}

在需要計算的時候直接調(diào)用const {sha1} = calculateSliceFileHash({file})即可

2. 根據(jù)hash查詢后端狀態(tài)

  async uploadFile(params) {
    // 獲取hash
    const {sha1} = await calculateSliceFileHash({ file })
    // 根據(jù)hash查詢文件狀態(tài)
    const {data} = await this.axios.post(`/api/xxx`, params)
    const { key, bucket, region, state, url } = data.data
    // state='hasHash' | 'hashIng' | 'notHash'
 ...
 }

3. 根據(jù)服務端的狀態(tài),返回上傳結(jié)果

async uploadFile(params) {
...
    // 文件存在,直接返回結(jié)果
    if (state === 'hasHash') {
      return Promise.resolve({url})
    }
    // 文件已上傳,后端處理中
    if (state === 'hashIng') {
      // 設置輪詢開始時間
      if (!params.pollStartTs) {
        params.pollStartTs = Date.now()
      } else if (Date.now() - params.pollStartTs >= 60000) {
        // 輪詢超過1分鐘認定為超時
        return Promise.reject({ error: '文件加載超時,請稍后再試' })
      }
      await sleep(1000) // 每隔1s輪詢
      await this.uploadFile(params)
    }
  	// state==='notHash'時,執(zhí)行下面的上傳
    return new Promise(async (resolve, reject) => {
      const cos = new Cos({
        getAuthorization: this.cosAuthorization({
          resolve,
          reject,
          bucket,
          key
        }).bind(this)
      })
      cos.sliceUploadFile(
        {
          Bucket: bucket,
          Region: region,
          Key: key,
          Body: file,
          SliceSize: 1024 * 1024 * 10, // 超10M使用分塊(cos單個塊最大不超過5GB)
          onProgress,
          onTaskReady
        },
        (error, data) => {
          if (error) {
            return reject({ error })
          }
          resolve(data)
        }
      )
    })
  }

批量上傳中應用秒傳

批量上傳也同樣適應,遍歷調(diào)用uploadFile({file: singleFile}),逐個處理。也可使用Promise.all(...),等待所有文件處理完后再返回結(jié)果集合。 注:建議使用遍歷逐個上傳,能有更好的用戶體驗。

存在的主要問題

上傳大文件并在瀏覽器中進行SHA1或MD5哈希計算時可能會導致瀏覽器崩潰,原因通常是在處理大文件時所需的計算和內(nèi)存資源超過了瀏覽器的能力

如上所示,通常的處理辦法包括: 通過setTimeoutrequestAnimationFrame分時段計算、切割合適的塊、使用Web Workers、使用Stream Processing優(yōu)化、優(yōu)化算法,內(nèi)存管理、在服務端計算等。
但最佳的處理辦法,是在瀏覽器中使用webworker多線程計算hash,同時需要兼顧其兼容性、線程數(shù)量(需根據(jù)實際應用調(diào)整),目前項目已做優(yōu)化、整體體驗尚佳。webworker在后面的文章中會有詳細的介紹。

總結(jié)

實現(xiàn)文件秒傳能夠顯著提升用戶的上傳體驗,特別是在處理大文件上傳時(上傳1GB大概20秒左右)
通過文件哈希比對、分塊上傳和斷點續(xù)傳等技術(shù),可以讓用戶感受到上傳速度的極大提升。
當然,文件秒傳的具體實現(xiàn)還是有一定的復雜性,需要前后端緊密協(xié)作,確保整個上傳過程的穩(wěn)定性和安全性。隨著技術(shù)的不斷進步,相信未來的文件上傳體驗將會更加流暢,讓用戶真正體驗到“秒傳”的魔力。

以上就是基于JavaScript實現(xiàn)文件秒傳功能的詳細內(nèi)容,更多關(guān)于JavaScript實現(xiàn)文件秒傳的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • RequireJS簡易繪圖程序開發(fā)

    RequireJS簡易繪圖程序開發(fā)

    這篇文章主要為大家詳細介紹了使用RequireJS簡易繪圖程序開發(fā),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-10-10
  • 原生js實現(xiàn)放大鏡組件

    原生js實現(xiàn)放大鏡組件

    這篇文章主要為大家詳細介紹了js實現(xiàn)放大鏡組件,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-01-01
  • es6中some和every方法使用簡單示例

    es6中some和every方法使用簡單示例

    JavaScript在ES6版本后提供了一些更加便捷的方法供開發(fā)者使用,實現(xiàn)原理其實是在對應的構(gòu)造函數(shù)原型提供方法,下面這篇文章主要給大家介紹了關(guān)于es6中some和every方法使用的相關(guān)資料,需要的朋友可以參考下
    2023-04-04
  • javascript中對變量類型的判斷方法

    javascript中對變量類型的判斷方法

    在JavaScript中,有5種基本數(shù)據(jù)類型和1種復雜數(shù)據(jù)類型,基本數(shù)據(jù)類型有:Undefined, Null, Boolean, Number和String;復雜數(shù)據(jù)類型是Object,Object中還細分了很多具體的類型,比如:Array, Function, Date等等
    2015-08-08
  • 如何實現(xiàn)瀏覽器上的右鍵菜單

    如何實現(xiàn)瀏覽器上的右鍵菜單

    如何實現(xiàn)瀏覽器上的右鍵菜單...
    2006-07-07
  • JavaScript簡單遍歷DOM對象所有屬性的實現(xiàn)方法

    JavaScript簡單遍歷DOM對象所有屬性的實現(xiàn)方法

    這篇文章主要介紹了JavaScript簡單遍歷DOM對象所有屬性的實現(xiàn)方法,涉及JavaScript針對頁面元素屬性操作的相關(guān)技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-10-10
  • JavaScript獲得指定對象大小的方法

    JavaScript獲得指定對象大小的方法

    這篇文章主要介紹了JavaScript獲得指定對象大小的方法,涉及javascript針對元素遍歷與屬性操作的相關(guān)技巧,需要的朋友可以參考下
    2015-07-07
  • 基于javascript的COOkie的操作實現(xiàn)只能點一次

    基于javascript的COOkie的操作實現(xiàn)只能點一次

    這篇文章主要介紹了基于javascript的COOkie的操作實現(xiàn)只能點一次,需要的朋友可以參考下
    2014-12-12
  • JS實現(xiàn)的4種數(shù)字千位符格式化方法分享

    JS實現(xiàn)的4種數(shù)字千位符格式化方法分享

    這篇文章主要介紹了JS實現(xiàn)的4種數(shù)字千位符格式化方法分享,本文給出了4種千分位格式化方法并對它們的性能做了比較,需要的朋友可以參考下
    2015-03-03
  • 純css實現(xiàn)窗戶玻璃雨滴逼真效果

    純css實現(xiàn)窗戶玻璃雨滴逼真效果

    css實現(xiàn)窗戶上水珠效果,效果特別逼真,窗外的雨淅淅瀝瀝飄打在玻璃上,看起來很像模糊的窗外,斜滴的雨露,接下來給大家一起來用CSS技術(shù)實現(xiàn)這樣一幅畫面,下面給大家分享使用純css實現(xiàn)窗戶玻璃雨滴逼真效果,感興趣的朋友快樂圍觀吧
    2015-08-08

最新評論