Electron 的斷點續下載


最近用 Electron 做了個壁紙程序,需要斷點續下載,在這里記錄一下。

HTTP斷點下載相關的報文

  • Accept-Ranges
    告訴客戶端服務器是否支持斷點續傳,服務器返回
  • Content-Range
    在HTTP協議中,響應首部 Content-Range 顯示的是一個數據片段在整個文件中的位置。
  • ETag
    資源標識 非必須 服務器返回
  • Last-Modified
    資源最后一次更新的時間 非必須 服務器返回
//響應示例 
accept-ranges: bytes
Content-Range: bytes 200-1000/67589 // 返回文件 200字節到1000字節 的數據,總文件大小67589字節
etag: "5f0dce96-48e"
last-modified: Tue, 14 Jul 2020 15:26:14 GMT
  • Range
    請求頭設置Range, 指定服務器返回指定區域內容,如果不設置Range會返回整個文件。服務器片段返回狀態碼是206,請求的范圍如果無效狀態碼會是416,全部返回狀態碼是200
//示例 
Range: bytes=0-499 表示第 0-499 字節范圍的內容 
Range: bytes=500-999 表示第 500-999 字節范圍的內容 
Range: bytes=-500 表示最后 500 字節的內容 
Range: bytes=500- 表示從第 500 字節開始到文件結束部分的內容 
Range: bytes=0-0,-1 表示第一個和最后一個字節 
Range: bytes=500-600,601-999 同時指定幾個范圍

Electron 斷點續下載方式

  • 使用 Chromium 的下載功能,在主進程里監聽 will-download 事件去處理
  • 使用 Electron 的net模塊或者 Node.js 的http/https模塊自己創建請求,記錄已下載位置

使用 Chromium 的下載

可以在渲染進程中和網頁一樣進行觸發下載(例如a標簽),也可以在主進程中使用 BrowserWindow.webContents 或 session 的 downloadURL觸發下載

//示例

//使用窗體 創建下載事件和監聽
let win = new BrowserWindow()
win.webContents.downloadURL(url)
win.webContents.session.on('will-download', (event,  downloadItem, webContents) => {
 event.preventDefault()//可以阻止下載
 //downloadItem 下載項目的 EventEmitter
})

//或者 使用默認session對象。
session.defaultSession.downloadURL(url)
session.defaultSession.on('will-download', (event,  downloadItem, webContents) => {

})

然后可以 will-download 事件中的 downloadItem 實例去存儲下載信息。等待程序再次啟動時通過 session.createInterruptedDownload 恢復上一次的下載
大致流程

//一個簡易示例
let cacheItem = {}
session.defaultSession.on('will-download', (e, item) => {
    const url = item.getURL()
    
    // 獲取文件的總大小
    const totalBytes = item.getTotalBytes();
    // 設置下載路徑
    const filePath = path.join(app.getPath("downloads"), item.getFilename());
    item.setSavePath(filePath);

    // 緩存downitem 將這些信息保存下來,
    cacheItem.path = item.getSavePath();//圖片地址
    cacheItem.eTag = item.getETag();//資源標識
    cacheItem.urlChain = item.getURLChain();//地址
    cacheItem.length = totalBytes//資源大小
    cacheItem.lastModified = item.getLastModifiedTime()//資源最后一次更新的時間
    cacheItem.startTime = item.getStartTime();

    let lastBytes = 0;

    // 監聽下載過程,計算並設置進度條進度
    item.on('updated', (event, state) => {
        if (state === 'interrupted') {
            console.log('下載已經中斷,可以恢復')
        } else if (state === 'progressing') {
            if (item.isPaused()) {
                console.log('暫停下載')
            } else {
                let offset = item.getReceivedBytes();
                cacheItem.speedBytes = offset - lastBytes;//下載速度
                cacheItem.offset = offset//已經下載
                lastBytes = offset
                console.log('下載中')
            }
        }
    })

    // 
    item.once('done', (event, state) => {
        if (state === 'interrupted') {
            console.log('下載已經中斷,無法恢復')
        }
        else if (state === 'cancelle') {
            console.log('下載取消')
        }
        else {
            console.log('下載完成')
        }
    })

    //是否可恢復下載
    if (item.canResume) {
        item.resume()
    }
})
//程序關閉時將 cacheItem 存儲下載

// ===> 程序 再次打開時

// 將上面存儲cacheItem信息讀取出來 恢復下載
session.defaultSession.createInterruptedDownload({
    path, 
    urlChain, 
    offset, // 下載斷點開始位置
    length, 
    lastModified, //
    eTag, // 
    startTime
})

相關的文檔地址 BrowserWindow ,Session , webContents, DownloadItem

創建請求實現續下載

大致上和上面是差不多的,記錄已下載文件信息,再次請求時候設置從指定位置開始請求數據


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM