当前位置:网站首页>File download manager realized by electron

File download manager realized by electron

2020-11-06 21:07:10 itread01

File download is a common business requirement in our development , such as : Export excel. web There are some limitations in downloading application files , Usually, the back end changes the response header information to `Content-Disposition: attachment; filename=xxx.pdf`, Trigger browser download behavior . stay electron Download behavior in , Will trigger session Of [will-download](https://www.electronjs.org/docs/api/session#instance-events) event . In this event, you can get [downloadItem](https://www.electronjs.org/docs/api/download-item) thing , Through [downloadItem](https://www.electronjs.org/docs/api/download-item) Object to implement a simple file download manager : ![demo.gif](https://cdn.nlark.com/yuque/0/2020/gif/1233799/1603696161110-a6e96603-0205-4807-9861-4b98eaaeee38.gif#align=left&display=inline&height=400&margin=%5Bobject%20Object%5D&name=demo.gif&originHeight=400&originWidth=599&size=133118&status=done&style=stroke&width=599) ## **1. How to trigger a download ** Because of electron Based on chromium Realized , By calling webContents Of [downloadURL](https://www.electronjs.org/docs/api/web-contents#contentsdownloadurlurl) Method , It's like calling chromium Download of the underlying implementation , The response header information is ignored , Trigger [will-download](https://www.electronjs.org/docs/api/session#instance-events) event . ```javascript // Trigger download win.webContents.downloadURL(url) // Monitoring will-download session.defaultSession.on('will-download', (event, item, webContents) => {}) ``` ## **2. Download process ** ![flow_chart.png](https://cdn.nlark.com/yuque/0/2020/png/1233799/1603443257821-3b875f31-208c-4b63-9c64-2fc69e4bb9a5.png#align=left&display=inline&height=664&margin=%5Bobject%20Object%5D&name=flow_chart.png&originHeight=1256&originWidth=518&size=90209&status=done&style=stroke&width=274) ## **3. Functional design ** Implementation of a simple file download manager, including the following functions : - Set the storage path - Pause / Restore and cancel - Download progress - Download speed - Download complete - Open file and open file location - File diagram - Download records ### **3.1 Set the storage path ** If the storage path is not set ,electron It will automatically pop up the storage dialog box of the system . Don't want to use the system's storage dialog box , have access to [setSavePath](https://www.electronjs.org/docs/api/download-item#downloaditemsetsavepathpath) Method , When there are duplicate files , Will directly cover the download . ```javascript item.setSavePath(path) ``` For a better user experience , Users can choose their own storage location to operate . When you click on the location input box , The rendering program passes through ipc Communicate with the main program , Open the system file and select the dialog box . ![select_path.gif](https://cdn.nlark.com/yuque/0/2020/gif/1233799/1604307314902-a39d6a37-c3f4-422b-a500-d1f6d603989a.gif#align=left&display=inline&height=561&margin=%5Bobject%20Object%5D&name=select_path.gif&originHeight=561&originWidth=818&size=701341&status=done&style=none&width=818) The main program implements code : ```typescript /** * Open the file selection box * @param oldPath - Last opened path */ const openFileDialog = async (oldPath: string = app.getPath('downloads')) => { if (!win) return oldPath const { canceled, filePaths } = await dialog.showOpenDialog(win, { title: ' Select storage location ', properties: ['openDirectory', 'createDirectory'], defaultPath: oldPath, }) return !canceled ? filePaths[0] : oldPath } ipcMain.handle('openFileDialog', (event, oldPath?: string) => openFileDialog(oldPath)) ``` Render program code : ```javascript const path = await ipcRenderer.invoke('openFileDialog', 'PATH') ``` ### **3.2 Pause / Restore and cancel ** Get [downloadItem](https://www.electronjs.org/docs/api/download-item) After , Pause 、 Resume and cancel calls separately `pause`、`resume` and `cancel` Method . When we want to delete the item in the list , You need to call first cancel Method to cancel the download . ### **3.3 Download progress ** stay DownloadItem Monitoring in updated event , The downloaded byte data can be obtained in real time , To calculate the download progress and download speed per second . ```javascript // Calculate download progress const progress = item.getReceivedBytes() / item.getTotalBytes() ``` ![download_progress.png](https://cdn.nlark.com/yuque/0/2020/png/1233799/1603443428433-83b1fb15-d070-43cc-a792-7e181add4cd2.png#align=left&display=inline&height=164&margin=%5Bobject%20Object%5D&name=download_progress.png&originHeight=164&originWidth=1192&size=28095&status=done&style=none&width=1192) When downloading , Want to be in Mac System's program dock and Windows The system's taskbar displays the download information , such as : - Downloads : Through app Of [badgeCount](https://www.electronjs.org/docs/api/app#appbadgecount-linux-macos) Property settings , To be 0 When , It doesn't show . It can also be done by dock Of [setBadge](https://www.electronjs.org/docs/api/app#appsetbadgecountcount-linux-macos) Method settings , This method supports strings , If you don't show , Need to be set to ''. - Download progress : Through windows [setProgressBar](https://www.electronjs.org/docs/api/browser-window#winsetprogressbarprogress-options) Method settings . > Because of Mac and Windows System differences , The number of downloads is only Mac In the system . add process.platform === 'darwin' Conditions , Avoid being in Africa Mac、Linux There is an abnormal error in the system . Download progress (Windows System work column 、Mac System dock ) Display effect : ![windows_progress.png](https://cdn.nlark.com/yuque/0/2020/png/1233799/1603443468964-53d9170a-1ac6-4b53-9a0c-8525ec43139a.png#align=left&display=inline&height=53&margin=%5Bobject%20Object%5D&name=windows_progress.png&originHeight=53&originWidth=196&size=10184&status=done&style=none&width=196) ![mac_download_progress.png](https://cdn.nlark.com/yuque/0/2020/png/1233799/1603443459605-0705af0d-ed7e-45ef-80b8-179b9d128078.png#align=left&display=inline&height=118&margin=%5Bobject%20Object%5D&name=mac_download_progress.png&originHeight=118&originWidth=108&size=17008&status=done&style=none&width=108) ```javascript // mac The dock shows the number of downloads : // Mode one app.badgeCount = 1 // Mode two app.dock.setBadge('1') // mac Cheng Shiwu 、windows The work column shows progress win.setProgressBar(progress) ``` ### **3.4 Download speed ** Because of [downloadItem](https://www.electronjs.org/docs/api/download-item) There is no direct method or property for us to get the download speed , Need to realize . > Ideas : stay updated In the event, through getReceivedBytes Method to get the download byte data minus the last download byte data . ```javascript // Record the last downloaded byte data let prevReceivedBytes = 0 item.on('updated', (e, state) => { const receivedBytes = item.getReceivedBytes() // Calculate the download rate per second downloadItem.speed = receivedBytes - prevReceivedBytes prevReceivedBytes = receivedBytes }) ``` > It should be noted that ,updated The execution time of the event is about 500ms once . ![updated_event.png](https://cdn.nlark.com/yuque/0/2020/png/1233799/1604396024337-516a4cb3-eb2b-4757-9115-8222d5bb7287.png#align=left&display=inline&height=286&margin=%5Bobject%20Object%5D&name=updated_event.png&originHeight=286&originWidth=878&size=128126&status=done&style=none&width=878) ### **3.5 Download complete ** When a file download is complete 、 Interrupt or be cancelled , You need to notify the render to modify the State , By monitoring [downloadItem](https://www.electronjs.org/docs/api/download-item) Of done event . ```javascript item.on('done', (e, state) => { downloadItem.state = state downloadItem.receivedBytes = item.getReceivedBytes() downloadItem.lastModifiedTime = item.getLastModifiedTime() // Notify the render program , Update download status webContents.send('downloadItemDone', downloadItem) }) ``` ### **3.6 Open file and open file location ** Use electron Of shell Module to open the file (openPath) And open the file location (showItemInFolder). > Because of openPath Method supports the return value `Promise `, When open files are not supported , The system will prompt you accordingly , and showItemInFolder Method return value is `void`. If you need a better user experience , You can use nodejs Of fs Module , First check if the file exists . ```typescript import fs from 'fs' // Open file const openFile = (path: string): boolean => { if (!fs.existsSync(path)) return false shell.openPath(path) return true } // Open the file location const openFileInFolder = (path: string): boolean => { if (!fs.existsSync(path)) return false shell.showItemInFolder(path) return true } ``` ### **3.7 File diagram ** It's very convenient to use app Modular [getFileIcon](https://www.electronjs.org/docs/api/app#appgetfileiconpath-options) Method to get the file icon associated with the system , The return is `Promise ` Type , We can use toDataURL Method is converted to base64, We don't have to deal with different file types and display different icons . ```typescript const getFileIcon = async (path: string) => { const iconDefault = './icon_default.png' if (!path) Promise.resolve(iconDefault) const icon = await app.getFileIcon(path, { size: 'normal' }) return icon.toDataURL() } ``` ### **3.8 Download records ** As more and more historical materials are downloaded , Use [electron-store](https://github.com/sindresorhus/electron-store) Save download records locally . ## ** other ** The address of the project : [https://github.com/tal-tech/electron-playground](https://github.com/tal-tech/electron-playground) If you want to see a more complete document , Please refer to the following document [Electron-Playground official document ](https://www.yuque.com/ezg6c4/

版权声明
本文为[itread01]所创,转载请带上原文链接,感谢