import { ElMessage } from 'element-plus'
|
import streamSaver from 'streamsaver'
|
import { _t, Language } from '@/libs/Language/Language'
|
import { downloadFile as downloadOpen } from './index'
|
import { Base } from '@/libs/Base/Base'
|
import slash from 'slash'
|
const request = Base.request
|
|
// if (process.env.NODE_ENV === 'development') {
|
// streamSaver.mitm = `${location.origin}/mitm/mitm.html?version=2.0.0`
|
// } else {
|
// streamSaver.mitm = `http://192.168.2.205:18000/resources/assets/files/mitm.html?version=2.0.0`
|
// }
|
declare global {
|
interface Window {
|
bridge: {
|
invoke: (callback: Function, ...args: any[]) => Promise<any>
|
}
|
request: {
|
get: (url: string, config?: any) => Promise<any>
|
}
|
electron: Record<string, any>
|
writer: any
|
reader: any
|
}
|
}
|
|
/**
|
* 显示文件夹选择对话框
|
* @param title 对话框标题
|
* @param buttonLabel 按钮标签
|
* @returns 文件夹路径
|
*/
|
export const showFolderDialog = (
|
title: string = '',
|
buttonLabel: string = '确定'
|
) => {
|
return window.bridge
|
? new Promise((rs) => {
|
const option = {
|
title,
|
buttonLabel,
|
properties: ['openDirectory'],
|
filters: [{ name: 'FileType', extensions: ['cmspkg'] }],
|
}
|
window.bridge
|
.invoke(async ({ electron }, option) => {
|
const { dialog, BrowserWindow } = electron
|
const win = BrowserWindow.getFocusedWindow()
|
const res = await dialog.showOpenDialog(win, option)
|
if (res !== undefined) {
|
return res
|
}
|
}, option)
|
.then((res) => {
|
!res.canceled && rs(res.filePaths[0])
|
})
|
})
|
: ''
|
}
|
/**
|
* 下载文件
|
* @param fileUrl 文件url
|
* @param fileName 文件名
|
* @param dir 文件保存路径
|
*/
|
export const downloadFileBuffer = async (
|
fileUrl: string,
|
fileName: string,
|
dir: string
|
) => {
|
if (window.bridge) {
|
let arraybuffer = await window.request.get(fileUrl, {
|
responseType: 'arraybuffer',
|
})
|
window.bridge.invoke(
|
({ electron, require }, dir, fileName, arrayBuffer) => {
|
const fs = require('fs')
|
const path = require('path')
|
const { shell } = electron
|
|
// 判断文件夹是否存在
|
let isExist = fs.existsSync(dir)
|
// 不存在,自动创建
|
if (!isExist) {
|
fs.mkdirSync(dir, {
|
recursive: true,
|
})
|
}
|
|
const filePath = path.join(dir, '/' + fileName)
|
const ui32 = new Uint8Array(arrayBuffer)
|
fs.writeFileSync(filePath, ui32)
|
shell.showItemInFolder(filePath)
|
},
|
dir,
|
fileName,
|
arraybuffer
|
)
|
}
|
}
|
/**
|
* 下载文件流
|
* @param fileUrl 文件url
|
* @param fileName 文件名
|
* @param dir 文件保存路径
|
*/
|
export const downloadFileStream = async (
|
fileUrl: string,
|
fileName: string,
|
dir: string
|
) => {
|
const url = fileUrl.includes('http')
|
? fileUrl
|
: `${location.origin}${fileUrl.startsWith('/') ? '' : '/'}${fileUrl}`
|
const fnStr = `
|
return new Promise((resolve, reject) => {
|
const { ipcRenderer } = require('electron');
|
ipcRenderer.on('export-operation-success', (event, message) => {
|
resolve(true)
|
});
|
ipcRenderer.on('export-operation-error', (event, message) => {
|
reject(false)
|
});
|
window.bridge.invoke(
|
({ electron, require }) => {
|
const fs = require('fs')
|
const path = require('path')
|
const http = require('http')
|
const { shell } = electron
|
const filePath = path.resolve('${dir}', '${fileName}')
|
const fileStream = fs.createWriteStream(filePath)
|
const { BrowserWindow } = electron
|
const win = BrowserWindow.getFocusedWindow()
|
http.get('${url}', {
|
headers: ${JSON.stringify(getHeaders())}
|
},(response) => {
|
response.pipe(fileStream)
|
fileStream.on('finish', () => {
|
fileStream.close()
|
shell.showItemInFolder(filePath)
|
win.webContents.send('export-operation-success');
|
})
|
|
fileStream.on('error', (error) => {
|
win.webContents.send('export-operation-error');
|
})
|
}).on('error', (error) => {
|
win.webContents.send('export-operation-error');
|
})
|
}
|
)
|
})`
|
const fn = new Function(fnStr)
|
|
return fn()
|
}
|
|
export const getHeaders = () => {
|
return {
|
Authorization: `Bearer ${sessionStorage.getItem('Token')}`,
|
'X-Project': sessionStorage.getItem('X-Project'),
|
'Accept-Language': Language.getLangReqHeader(),
|
}
|
}
|
|
const getFile = async (url: string, filename: string) => {
|
const res = await request.get(url, {
|
responseType: 'blob',
|
})
|
return downloadOpen(res, filename)
|
}
|
/**
|
* 下载文件
|
* @param url 文件url
|
* @param filename 文件名
|
*/
|
export const browserDownload = (
|
url: string,
|
filename = '',
|
isOpen = true,
|
windowFeatures = ''
|
) => {
|
return new Promise(async (resolve, reject) => {
|
if (isOpen) {
|
window.open(url, '_blank', windowFeatures)
|
return resolve(true)
|
}
|
const headers = getHeaders()
|
if (!navigator.onLine) {
|
await getFile(url, filename)
|
return resolve(true)
|
}
|
fetch(url, {
|
method: 'get',
|
headers,
|
}).then((res) => {
|
if (res.status !== 200) {
|
ElMessage.error(_t('文件错误,下载失败'))
|
reject(false)
|
return
|
}
|
const size = Number(res.headers.get('content-length'))
|
const readableStream = res.body
|
const fileStream = streamSaver.createWriteStream(filename, {
|
size,
|
})
|
if (window.WritableStream && readableStream?.pipeTo) {
|
return readableStream?.pipeTo(fileStream).then((res) => {
|
resolve(true)
|
console.log('done writeen')
|
})
|
}
|
window.writer = fileStream.getWriter()
|
const reader = res.body?.getReader()
|
const pump = () =>
|
reader?.read().then((res) => {
|
if (res.done) {
|
window.writer.close()
|
} else {
|
window.reader.write(res.value).then(pump)
|
}
|
})
|
pump()
|
})
|
return
|
})
|
}
|
function replaceSingleBackslash(str) {
|
return str.replace(/(?<!\\)\\(?!\\)/g, '/')
|
}
|
/**
|
* 下载文件
|
* @param fileUrl 文件url
|
* @param fileName 文件名
|
* @param title 对话框标题
|
* @param buttonLabel 按钮标签
|
* @param params 请求参数
|
* @param isOpen 是否打开新窗口
|
* @param windowFeatures 窗口特性
|
*/
|
export const downloadFile = async ({
|
fileUrl,
|
fileName,
|
title = '',
|
buttonLabel = '确定',
|
params,
|
isOpen = false,
|
windowFeatures = '',
|
callback,
|
}: {
|
fileUrl: string
|
fileName: string
|
title?: string
|
buttonLabel?: string
|
params?: Record<string, any>
|
isOpen?: boolean
|
method?: string
|
data?: any
|
windowFeatures?: string
|
callback?: () => void
|
}) => {
|
const str = new URLSearchParams(
|
params as unknown as URLSearchParams
|
).toString()
|
const p = str ? `?${str}` : ''
|
if (window.bridge && window.bridge.invoke && window.electron) {
|
const dir = (await showFolderDialog(title, buttonLabel)) as string
|
callback?.()
|
if (dir) {
|
const newDir = replaceSingleBackslash(slash(dir))
|
return downloadFileStream(fileUrl + p, fileName, newDir)
|
} else {
|
ElMessage.warning('已取消下载')
|
return
|
}
|
} else {
|
return await browserDownload(fileUrl + p, fileName, isOpen, windowFeatures)
|
}
|
}
|
|
export default {
|
showFolderDialog,
|
downloadFileBuffer,
|
downloadFileStream,
|
downloadFile,
|
}
|