Skip to content

Commit

Permalink
feat: custom download behavior
Browse files Browse the repository at this point in the history
  • Loading branch information
Linkontoask committed Dec 31, 2020
1 parent f014352 commit 2683b55
Show file tree
Hide file tree
Showing 8 changed files with 194 additions and 64 deletions.
3 changes: 2 additions & 1 deletion src/electron/event/action-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ export const enum DownloadIpcType {
SET_DOWNLOAD_PATH = 'SET_DOWNLOAD_PATH',
DOWNLOAD_PROGRESS = 'DOWNLOAD_PROGRESS',
DOWNLOAD_START = 'DOWNLOAD_START',
DOWNLOAD_END = 'DOWNLOAD_END'
DOWNLOAD_END = 'DOWNLOAD_END',
DOWNLOAD_TASK = 'DOWNLOAD_TASK'
}

export const enum MiddlewareView {
Expand Down
202 changes: 153 additions & 49 deletions src/electron/event/ipc-main/download.ts
Original file line number Diff line number Diff line change
@@ -1,60 +1,164 @@
import { BrowserWindow, DownloadItem } from 'electron'
import { BrowserWindow, DownloadItem, ipcMain, net } from 'electron'
import { getUserOS, join } from '@/electron/utils/index'
import { DownloadIpcType } from '../action-types'
import { writeFile } from 'fs'
import { DownloadData } from '../../preload/ipc'
import throttle from 'lodash/throttle'
import store from '@/electron/store/index'

interface MainDownloadData extends DownloadData {
win: BrowserWindow
}

const downloadStart = ({
win,
name
}: Pick<MainDownloadData, 'win' | 'name'>) => {
win.webContents.send(DownloadIpcType.DOWNLOAD_START, {
state: 'start',
name
})
}
const downloadProgress = throttle(
({
win,
receive,
total,
name
}: Pick<MainDownloadData, 'win' | 'receive' | 'total' | 'name'>) => {
const schedule = receive / total
win.webContents.send(DownloadIpcType.DOWNLOAD_PROGRESS, {
state: 'progressing',
name: name,
receive: receive,
total: total,
schedule
})
},
200
)

const downloadEnd = ({
win,
error,
name,
state
}: Pick<MainDownloadData, 'win' | 'error' | 'name' | 'state'>) => {
win.webContents.send(DownloadIpcType.DOWNLOAD_END, {
state,
name,
error
})
}

export const downloadIntercept = (win: BrowserWindow) => {
win.webContents.session.on(
'will-download',
(event, item: DownloadItem, content) => {
const downloadPath = store.get(
'downloadPath',
join(getUserOS().homedir, '/Music')
)
const path = join(downloadPath, item.getFilename())
item.setSavePath(path)
win.webContents.send(DownloadIpcType.DOWNLOAD_START, {
name: item.getFilename(),
state: 'start'
})
item.on('updated', (event, state) => {
if (state === 'progressing') {
if (win.isDestroyed()) {
return
}
const receive = item.getReceivedBytes()
const total = item.getTotalBytes()
const schedule = Number((receive / total).toFixed(2))
win.webContents.send(DownloadIpcType.DOWNLOAD_PROGRESS, {
state: state,
name: item.getFilename(),
receive,
total,
schedule
const downloadPath = store.get(
'downloadPath',
join(getUserOS().homedir, '/Downloads')
)

ipcMain.on(
DownloadIpcType.DOWNLOAD_TASK,
async (event, { name, url, suffix }: { [x: string]: string }) => {
console.log(url, name, suffix)
const request = await net.request(url)
request.on('response', response => {
downloadStart({
win,
name
})
console.log(`HEADERS: ${JSON.stringify(response.headers)}`)
const totalBytes = parseInt(
response.headers['content-length'] as string
)
let receivedBytes = 0
const chunks: Buffer[] = []
response.on('data', chunk => {
chunks.push(chunk)
receivedBytes += chunk.length
downloadProgress({
win,
name,
receive: receivedBytes,
total: totalBytes
})
})
response.on('end', () => {
const buffer = Buffer.concat(chunks)
const path = join(downloadPath, name + suffix)
console.log(path)
writeFile(path, buffer, err => {
console.log(err)
if (err) {
downloadEnd({
win,
name,
error: err,
state: 'interrupted'
})
} else {
downloadEnd({
win,
name,
error: err,
state: 'completed'
})
}
})
if (schedule) {
win.setProgressBar(schedule)
}
} else {
console.warn('Dwonload Error:', item.getFilename(), state)
}
})
item.once('done', (event, state) => {
win.webContents.send(DownloadIpcType.DOWNLOAD_END, {
state: state,
name: item.getFilename(),
receive: item.getReceivedBytes(),
total: item.getTotalBytes()
})
if (state === 'completed') {
if (process.platform === 'darwin') {
//
}
win.setProgressBar(-1)

// Set the song comment after the download is complete
}
})
request.end()
}
)
win.webContents.session.on('will-download', (event, item: DownloadItem) => {
const path = join(downloadPath, item.getFilename())
item.setSavePath(path)
const name = item.getFilename()
downloadStart({
name,
win
})
const total = item.getTotalBytes()
item.on('updated', (event, state) => {
if (state === 'progressing') {
if (win.isDestroyed()) {
return
}
const receive = item.getReceivedBytes()
const schedule = receive / total
downloadProgress({
win,
receive,
total,
name
})
if (schedule) {
win.setProgressBar(schedule)
}
} else {
downloadEnd({
win,
name,
state,
error: 'Dwonload Error: ' + name + state
})
console.warn('Dwonload Error:', item.getFilename(), state)
}
})
item.once('done', (event, state) => {
downloadEnd({
win,
name,
state
})
if (state === 'completed') {
if (process.platform === 'darwin') {
//
}
win.setProgressBar(-1)

// Set the song comment after the download is complete
}
})
})
}
3 changes: 2 additions & 1 deletion src/electron/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,9 @@ app.on('activate', () => {
app.on('ready', async () => {
session.defaultSession.webRequest.onBeforeSendHeaders((details, callback) => {
const location = new URL(details.url)
if (location.port === '80') {
if (location.port === '') {
details.requestHeaders['Origin'] = location.origin
details.requestHeaders['Referer'] = location.origin
}
callback({ requestHeaders: details.requestHeaders })
})
Expand Down
12 changes: 7 additions & 5 deletions src/electron/preload/ipc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ import { DownloadIpcType } from '@/electron/event/action-types'
import { suggested, success, error } from '@/hooks/index'
import store, { RootMutations } from '@/store'

interface Process {
state: 'progressing' | 'completed' | 'interrupted' | 'cancelled'
export interface DownloadData {
state: 'progressing' | 'completed' | 'interrupted' | 'cancelled' | 'start'
name: string
receive: number
total: number
schedule: number
error?: NodeJS.ErrnoException | null | string
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
Expand All @@ -17,7 +18,7 @@ export const registerIPC = (app: App) => {
v.ipcRenderer.on(DownloadIpcType.DOWNLOAD_START, (event, arg) => {
store.commit(
RootMutations.UPDATE_PERECENTAGE,
Math.floor(Math.random() * 10)
Math.floor((Math.random() * 10) / 100)
)
suggested('下载中...', {
key: arg.name
Expand All @@ -26,12 +27,13 @@ export const registerIPC = (app: App) => {

v.ipcRenderer.on(
DownloadIpcType.DOWNLOAD_END,
(event, arg: Pick<Process, 'name' | 'state'>) => {
(event, arg: Pick<DownloadData, 'name' | 'state' | 'error'>) => {
if (arg.state === 'completed') {
success('下载完成', {
key: arg.name
})
} else {
console.log(arg.error)
error('下载失败', {
key: arg.name
})
Expand All @@ -41,7 +43,7 @@ export const registerIPC = (app: App) => {

v.ipcRenderer.on(
DownloadIpcType.DOWNLOAD_PROGRESS,
(event, arg: Process) => {
(event, arg: DownloadData) => {
if (arg.state === 'progressing') {
store.commit(RootMutations.UPDATE_PERECENTAGE, arg.schedule)
}
Expand Down
10 changes: 10 additions & 0 deletions src/electron/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,3 +126,13 @@ export const readPathMusic = async (abPath: string[]) => {

return fls
}

export const saveBlob = (blob: Blob) => {
const reader = new FileReader()
reader.onload = () => {
if (reader.readyState == 2 && reader.result) {
const buffer = Buffer.from(reader.result)
}
}
reader.readAsArrayBuffer(blob)
}
22 changes: 18 additions & 4 deletions src/pages/download/sage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,28 @@ import { getMusicUrl } from '@/shared/music-shared'
import { download } from '@/utils/index'
import { importIpc } from '@/electron/event/ipc-browser'
import { DownloadIpcType } from '@/electron/event/action-types'
import { Platform } from '@/config/build'

const { VUE_APP_PLATFORM } = process.env

export const actions: ActionTree<DownloadState, RootState> = {
async [DownloadActions.DOWNLOAD_MUSIC]({ commit }, song: SongsDetail) {
const url = await getMusicUrl(song.id)
song.size = url[0].size
const songBase = await getMusicUrl(song.id)
song.size = songBase[0].size
const url = songBase[0].url
commit(DownloadMutations.SET_DOWNLOAD_MUSIC, song)
// TODO ws protocol to be supported, download progress to be discussed
download(url[0].url, song.name)
if (VUE_APP_PLATFORM === Platform.BROWSER) {
// TODO ws protocol to be supported, download progress to be discussed
download(url, song.name)
}
if (VUE_APP_PLATFORM === Platform.ELECTRON) {
const v = await importIpc()
v.sendAsyncIpcRendererEvent(DownloadIpcType.DOWNLOAD_TASK, {
name: song.name,
suffix: '.mp3',
url
})
}
}
}

Expand Down
2 changes: 0 additions & 2 deletions src/pages/setting/view/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ export const Setting = defineComponent({
() => route.params.location,
loc => {
jumpTop(loc as string)
console.log(loc)
}
)

Expand All @@ -92,7 +91,6 @@ export const Setting = defineComponent({
}
}
}
console.log(areaFormat.value)
}
})

Expand Down
4 changes: 2 additions & 2 deletions src/store/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { createStore, MutationTree, createLogger } from 'vuex'
import { FooterMutations } from '@/interface'
import { AllMutations, PlaySource } from '@/interface/index'
import { getNodeEnv } from '@/utils/index'
import { getNodeEnv, toFixed } from '@/utils/index'
import createPersistedState from 'vuex-persistedstate'
import modules from '@/modules/index'

Expand Down Expand Up @@ -67,7 +67,7 @@ const mutations: MutationTree<RootState> = {
state.historyRoute.canBeCollect = collect
},
[RootMutations.UPDATE_PERECENTAGE](state, percentage: number) {
state.percentage = percentage * 100
state.percentage = toFixed(percentage * 100, 2)
}
}

Expand Down

0 comments on commit 2683b55

Please sign in to comment.