jan/electron/handlers/download.ts
Louis 5890ade451
chore: server download progress + S3 (#1925)
* fix: reduce the number of api call

Signed-off-by: James <james@jan.ai>

* fix: download progress

Signed-off-by: James <james@jan.ai>

* chore: save blob

* fix: server boot up

* fix: download state not updating

Signed-off-by: James <james@jan.ai>

* fix: copy assets

* Add Dockerfile CPU for Jan Server and Jan Web

* Add Dockerfile GPU for Jan Server and Jan Web

* feat: S3 adapter

* Update check find count from ./pre-install and correct copy:asserts command

* server add bundleDependencies @janhq/core

* server add bundleDependencies @janhq/core

* fix: update success/failed download state (#1945)

* fix: update success/failed download state

Signed-off-by: James <james@jan.ai>

* fix: download model progress and state handling for both Desktop and Web

---------

Signed-off-by: James <james@jan.ai>
Co-authored-by: James <james@jan.ai>
Co-authored-by: Louis <louis@jan.ai>

* chore: refactor

* fix: load models empty first time open

* Add Docker compose

* fix: assistants onUpdate

---------

Signed-off-by: James <james@jan.ai>
Co-authored-by: James <james@jan.ai>
Co-authored-by: Hien To <tominhhien97@gmail.com>
Co-authored-by: NamH <NamNh0122@gmail.com>
2024-02-07 17:54:35 +07:00

133 lines
4.4 KiB
TypeScript

import { ipcMain } from 'electron'
import { resolve } from 'path'
import { WindowManager } from './../managers/window'
import request from 'request'
import { createWriteStream, renameSync } from 'fs'
import { DownloadEvent, DownloadRoute } from '@janhq/core'
const progress = require('request-progress')
import {
DownloadManager,
getJanDataFolderPath,
normalizeFilePath,
} from '@janhq/core/node'
export function handleDownloaderIPCs() {
/**
* Handles the "pauseDownload" IPC message by pausing the download associated with the provided fileName.
* @param _event - The IPC event object.
* @param fileName - The name of the file being downloaded.
*/
ipcMain.handle(DownloadRoute.pauseDownload, async (_event, fileName) => {
DownloadManager.instance.networkRequests[fileName]?.pause()
})
/**
* Handles the "resumeDownload" IPC message by resuming the download associated with the provided fileName.
* @param _event - The IPC event object.
* @param fileName - The name of the file being downloaded.
*/
ipcMain.handle(DownloadRoute.resumeDownload, async (_event, fileName) => {
DownloadManager.instance.networkRequests[fileName]?.resume()
})
/**
* Handles the "abortDownload" IPC message by aborting the download associated with the provided fileName.
* The network request associated with the fileName is then removed from the networkRequests object.
* @param _event - The IPC event object.
* @param fileName - The name of the file being downloaded.
*/
ipcMain.handle(DownloadRoute.abortDownload, async (_event, fileName) => {
const rq = DownloadManager.instance.networkRequests[fileName]
if (rq) {
DownloadManager.instance.networkRequests[fileName] = undefined
rq?.abort()
} else {
WindowManager?.instance.currentWindow?.webContents.send(
DownloadEvent.onFileDownloadError,
{
fileName,
err: { message: 'aborted' },
}
)
}
})
/**
* Downloads a file from a given URL.
* @param _event - The IPC event object.
* @param url - The URL to download the file from.
* @param fileName - The name to give the downloaded file.
*/
ipcMain.handle(
DownloadRoute.downloadFile,
async (_event, url, localPath, network) => {
const strictSSL = !network?.ignoreSSL
const proxy = network?.proxy?.startsWith('http')
? network.proxy
: undefined
if (typeof localPath === 'string') {
localPath = normalizeFilePath(localPath)
}
const array = localPath.split('/')
const fileName = array.pop() ?? ''
const modelId = array.pop() ?? ''
const destination = resolve(getJanDataFolderPath(), localPath)
const rq = request({ url, strictSSL, proxy })
// Put request to download manager instance
DownloadManager.instance.setRequest(localPath, rq)
// Downloading file to a temp file first
const downloadingTempFile = `${destination}.download`
progress(rq, {})
.on('progress', function (state: any) {
WindowManager?.instance.currentWindow?.webContents.send(
DownloadEvent.onFileDownloadUpdate,
{
...state,
fileName,
modelId,
}
)
})
.on('error', function (err: Error) {
WindowManager?.instance.currentWindow?.webContents.send(
DownloadEvent.onFileDownloadError,
{
fileName,
err,
modelId,
}
)
})
.on('end', function () {
if (DownloadManager.instance.networkRequests[localPath]) {
// Finished downloading, rename temp file to actual file
renameSync(downloadingTempFile, destination)
WindowManager?.instance.currentWindow?.webContents.send(
DownloadEvent.onFileDownloadSuccess,
{
fileName,
modelId,
}
)
DownloadManager.instance.setRequest(localPath, undefined)
} else {
WindowManager?.instance.currentWindow?.webContents.send(
DownloadEvent.onFileDownloadError,
{
fileName,
modelId,
err: { message: 'aborted' },
}
)
}
})
.pipe(createWriteStream(downloadingTempFile))
}
)
}