123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- 'use strict';
- const path = require('path');
- const electron = require('electron');
- const unusedFilename = require('unused-filename');
- const pupa = require('pupa');
- const extName = require('ext-name');
- const {app, shell} = electron;
- function getFilenameFromMime(name, mime) {
- const exts = extName.mime(mime);
- if (exts.length !== 1) {
- return name;
- }
- return `${name}.${exts[0].ext}`;
- }
- function registerListener(session, options, cb = () => {}) {
- const downloadItems = new Set();
- let receivedBytes = 0;
- let completedBytes = 0;
- let totalBytes = 0;
- const activeDownloadItems = () => downloadItems.size;
- const progressDownloadItems = () => receivedBytes / totalBytes;
- options = Object.assign({
- showBadge: true
- }, options);
- const listener = (e, item, webContents) => {
- downloadItems.add(item);
- totalBytes += item.getTotalBytes();
- let hostWebContents = webContents;
- if (webContents.getType() === 'webview') {
- ({hostWebContents} = webContents);
- }
- const win = electron.BrowserWindow.fromWebContents(hostWebContents);
- const dir = options.directory || app.getPath('downloads');
- let filePath;
- if (options.filename) {
- filePath = path.join(dir, options.filename);
- } else {
- const filename = item.getFilename();
- const name = path.extname(filename) ? filename : getFilenameFromMime(filename, item.getMimeType());
- filePath = unusedFilename.sync(path.join(dir, name));
- }
- const errorMessage = options.errorMessage || 'The download of {filename} was interrupted';
- const errorTitle = options.errorTitle || 'Download Error';
- if (!options.saveAs) {
- item.setSavePath(filePath);
- }
- if (typeof options.onStarted === 'function') {
- options.onStarted(item);
- }
- item.on('updated', () => {
- receivedBytes = [...downloadItems].reduce((receivedBytes, item) => {
- receivedBytes += item.getReceivedBytes();
- return receivedBytes;
- }, completedBytes);
- if (options.showBadge && ['darwin', 'linux'].includes(process.platform)) {
- app.setBadgeCount(activeDownloadItems());
- }
- if (!win.isDestroyed()) {
- win.setProgressBar(progressDownloadItems());
- }
- if (typeof options.onProgress === 'function') {
- options.onProgress(progressDownloadItems());
- }
- });
- item.on('done', (e, state) => {
- completedBytes += item.getTotalBytes();
- downloadItems.delete(item);
- if (options.showBadge && ['darwin', 'linux'].includes(process.platform)) {
- app.setBadgeCount(activeDownloadItems());
- }
- if (!win.isDestroyed() && !activeDownloadItems()) {
- win.setProgressBar(-1);
- receivedBytes = 0;
- completedBytes = 0;
- totalBytes = 0;
- }
- if (options.unregisterWhenDone) {
- session.removeListener('will-download', listener);
- }
- if (state === 'cancelled') {
- if (typeof options.onCancel === 'function') {
- options.onCancel(item);
- }
- } else if (state === 'interrupted') {
- const message = pupa(errorMessage, {filename: item.getFilename()});
- electron.dialog.showErrorBox(errorTitle, message);
- cb(new Error(message));
- } else if (state === 'completed') {
- if (process.platform === 'darwin') {
- app.dock.downloadFinished(filePath);
- }
- if (options.openFolderWhenDone) {
- shell.showItemInFolder(path.join(dir, item.getFilename()));
- }
- cb(null, item);
- }
- });
- };
- session.on('will-download', listener);
- }
- module.exports = (options = {}) => {
- app.on('session-created', session => {
- registerListener(session, options);
- });
- };
- module.exports.download = (win, url, options) => new Promise((resolve, reject) => {
- options = Object.assign({}, options, {unregisterWhenDone: true});
- registerListener(win.webContents.session, options, (err, item) => {
- if (err) {
- reject(err);
- } else {
- resolve(item);
- }
- });
- win.webContents.downloadURL(url);
- });
|