mirror of
https://github.com/Kuingsmile/PicList.git
synced 2026-09-05 23:47:43 +08:00
✨ Feature: downloaded file or folder can keey folder structure now
This commit is contained in:
@@ -59,6 +59,7 @@ const uploadFile = async () => {
|
|||||||
const progressBar = Math.round((progress.loaded / progress.total) * 100)
|
const progressBar = Math.round((progress.loaded / progress.total) * 100)
|
||||||
process.stdout.write(`\r${progressBar}% ${fileName}`)
|
process.stdout.write(`\r${progressBar}% ${fileName}`)
|
||||||
})
|
})
|
||||||
|
console.log('\n')
|
||||||
await parallelUploads3.done()
|
await parallelUploads3.done()
|
||||||
console.log(`${fileName} uploaded!`)
|
console.log(`${fileName} uploaded!`)
|
||||||
if (!versionFileHasUploaded) {
|
if (!versionFileHasUploaded) {
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import UpDownTaskQueue,
|
|||||||
commonTaskStatus
|
commonTaskStatus
|
||||||
} from '../datastore/upDownTaskQueue'
|
} from '../datastore/upDownTaskQueue'
|
||||||
import { ManageLogger } from '../utils/logger'
|
import { ManageLogger } from '../utils/logger'
|
||||||
|
import { cancelDownloadLoadingFileList, refreshDownloadFileTransferList } from '@/manage/utils/static'
|
||||||
|
|
||||||
// 坑爹阿里云 返回数据类型标注和实际各种不一致
|
// 坑爹阿里云 返回数据类型标注和实际各种不一致
|
||||||
class AliyunApi {
|
class AliyunApi {
|
||||||
@@ -211,6 +212,53 @@ class AliyunApi {
|
|||||||
return res && res.res.status === 200
|
return res && res.res.status === 200
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getBucketListRecursively (configMap: IStringKeyMap): Promise<any> {
|
||||||
|
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
|
const { bucketName: bucket, bucketConfig: { Location: region }, prefix, cancelToken } = configMap
|
||||||
|
const slicedPrefix = prefix.slice(1)
|
||||||
|
const urlPrefix = configMap.customUrl || `https://${bucket}.${region}.aliyuncs.com`
|
||||||
|
let marker
|
||||||
|
const cancelTask = [false]
|
||||||
|
ipcMain.on(cancelDownloadLoadingFileList, (_evt: IpcMainEvent, token: string) => {
|
||||||
|
if (token === cancelToken) {
|
||||||
|
cancelTask[0] = true
|
||||||
|
ipcMain.removeAllListeners(cancelDownloadLoadingFileList)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
let res = {} as any
|
||||||
|
const result = {
|
||||||
|
fullList: <any>[],
|
||||||
|
success: false,
|
||||||
|
finished: false
|
||||||
|
}
|
||||||
|
const client = this.getNewCtx(region, bucket)
|
||||||
|
do {
|
||||||
|
res = await client.listV2({
|
||||||
|
prefix: slicedPrefix === '' ? undefined : slicedPrefix,
|
||||||
|
'max-keys': '1000',
|
||||||
|
'continuation-token': marker
|
||||||
|
}, {
|
||||||
|
timeout: this.timeOut
|
||||||
|
})
|
||||||
|
if (res && res.res.statusCode === 200) {
|
||||||
|
res.objects && res.objects.forEach((item: OSS.ObjectMeta) => {
|
||||||
|
item.size !== 0 && result.fullList.push(this.formatFile(item, slicedPrefix, urlPrefix))
|
||||||
|
})
|
||||||
|
window.webContents.send(refreshDownloadFileTransferList, result)
|
||||||
|
} else {
|
||||||
|
result.finished = true
|
||||||
|
window.webContents.send(refreshDownloadFileTransferList, result)
|
||||||
|
ipcMain.removeAllListeners(cancelDownloadLoadingFileList)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
marker = res.nextContinuationToken
|
||||||
|
} while (res.isTruncated === true && !cancelTask[0])
|
||||||
|
result.success = !cancelTask[0]
|
||||||
|
result.finished = true
|
||||||
|
window.webContents.send(refreshDownloadFileTransferList, result)
|
||||||
|
ipcMain.removeAllListeners(cancelDownloadLoadingFileList)
|
||||||
|
}
|
||||||
|
|
||||||
async getBucketListBackstage (configMap: IStringKeyMap): Promise<any> {
|
async getBucketListBackstage (configMap: IStringKeyMap): Promise<any> {
|
||||||
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
const { bucketName: bucket, bucketConfig: { Location: region }, prefix, cancelToken } = configMap
|
const { bucketName: bucket, bucketConfig: { Location: region }, prefix, cancelToken } = configMap
|
||||||
@@ -256,7 +304,7 @@ class AliyunApi {
|
|||||||
}
|
}
|
||||||
marker = res.nextContinuationToken
|
marker = res.nextContinuationToken
|
||||||
} while (res.isTruncated === true && !cancelTask[0])
|
} while (res.isTruncated === true && !cancelTask[0])
|
||||||
result.success = true
|
result.success = !cancelTask[0]
|
||||||
result.finished = true
|
result.finished = true
|
||||||
window.webContents.send('refreshFileTransferList', result)
|
window.webContents.send('refreshFileTransferList', result)
|
||||||
ipcMain.removeAllListeners('cancelLoadingFileList')
|
ipcMain.removeAllListeners('cancelLoadingFileList')
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import UpDownTaskQueue,
|
|||||||
} from '../datastore/upDownTaskQueue'
|
} from '../datastore/upDownTaskQueue'
|
||||||
import fs from 'fs-extra'
|
import fs from 'fs-extra'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
|
import { cancelDownloadLoadingFileList, refreshDownloadFileTransferList } from '@/manage/utils/static'
|
||||||
|
|
||||||
class GithubApi {
|
class GithubApi {
|
||||||
token: string
|
token: string
|
||||||
@@ -147,6 +148,57 @@ class GithubApi {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getBucketListRecursively (configMap: IStringKeyMap): Promise<any> {
|
||||||
|
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
|
const { bucketName: repo, customUrl: branch, prefix, cancelToken, cdnUrl } = configMap
|
||||||
|
const slicedPrefix = prefix.replace(/^\//, '').replace(/\/$/, '')
|
||||||
|
const cancelTask = [false]
|
||||||
|
ipcMain.on(cancelDownloadLoadingFileList, (_evt: IpcMainEvent, token: string) => {
|
||||||
|
if (token === cancelToken) {
|
||||||
|
cancelTask[0] = true
|
||||||
|
ipcMain.removeAllListeners(cancelDownloadLoadingFileList)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
let res = {} as any
|
||||||
|
const result = {
|
||||||
|
fullList: <any>[],
|
||||||
|
success: false,
|
||||||
|
finished: false
|
||||||
|
}
|
||||||
|
const treeQueue = [slicedPrefix]
|
||||||
|
while (treeQueue.length) {
|
||||||
|
if (cancelTask[0]) {
|
||||||
|
result.finished = true
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
const currentPrefix = treeQueue[0]
|
||||||
|
res = await got(
|
||||||
|
`${this.baseUrl}/repos/${this.username}/${repo}/git/trees/${branch}:${treeQueue.shift()}`,
|
||||||
|
getOptions('GET', this.commonHeaders, {}, 'json', undefined, undefined, this.proxy)
|
||||||
|
) as any
|
||||||
|
if (res && res.statusCode === 200) {
|
||||||
|
const { tree } = res.body
|
||||||
|
tree.forEach((item: any) => {
|
||||||
|
if (item.type === 'tree') {
|
||||||
|
treeQueue.push(`${currentPrefix}/${item.path}`)
|
||||||
|
} else {
|
||||||
|
result.fullList.push(this.formatFile(item, currentPrefix, branch, repo, cdnUrl))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
window.webContents.send(refreshDownloadFileTransferList, result)
|
||||||
|
} else {
|
||||||
|
result.finished = true
|
||||||
|
window.webContents.send(refreshDownloadFileTransferList, result)
|
||||||
|
ipcMain.removeAllListeners(cancelDownloadLoadingFileList)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.success = true
|
||||||
|
result.finished = true
|
||||||
|
window.webContents.send(refreshDownloadFileTransferList, result)
|
||||||
|
ipcMain.removeAllListeners(cancelDownloadLoadingFileList)
|
||||||
|
}
|
||||||
|
|
||||||
async getBucketListBackstage (configMap: IStringKeyMap): Promise<any> {
|
async getBucketListBackstage (configMap: IStringKeyMap): Promise<any> {
|
||||||
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
const { bucketName: repo, customUrl: branch, prefix, cancelToken, cdnUrl } = configMap
|
const { bucketName: repo, customUrl: branch, prefix, cancelToken, cdnUrl } = configMap
|
||||||
|
|||||||
@@ -147,9 +147,9 @@ class ImgurApi {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
initPage++
|
initPage++
|
||||||
} while (res.body.data.length > 0)
|
} while (res.body.data.length > 0 && !cancelTask[0])
|
||||||
}
|
}
|
||||||
result.success = true
|
result.success = !cancelTask[0]
|
||||||
result.finished = true
|
result.finished = true
|
||||||
window.webContents.send('refreshFileTransferList', result)
|
window.webContents.send('refreshFileTransferList', result)
|
||||||
ipcMain.removeAllListeners('cancelLoadingFileList')
|
ipcMain.removeAllListeners('cancelLoadingFileList')
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import UpDownTaskQueue,
|
|||||||
commonTaskStatus
|
commonTaskStatus
|
||||||
} from '../datastore/upDownTaskQueue'
|
} from '../datastore/upDownTaskQueue'
|
||||||
import { ManageLogger } from '../utils/logger'
|
import { ManageLogger } from '../utils/logger'
|
||||||
|
import { cancelDownloadLoadingFileList, refreshDownloadFileTransferList } from '@/manage/utils/static'
|
||||||
|
|
||||||
class QiniuApi {
|
class QiniuApi {
|
||||||
mac: qiniu.auth.digest.Mac
|
mac: qiniu.auth.digest.Mac
|
||||||
@@ -246,6 +247,62 @@ class QiniuApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getBucketListRecursively (configMap: IStringKeyMap): Promise<any> {
|
||||||
|
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
|
const { bucketName: bucket, prefix, cancelToken, customUrl: urlPrefix } = configMap
|
||||||
|
let marker = undefined as any
|
||||||
|
const slicedPrefix = prefix.slice(1)
|
||||||
|
const cancelTask = [false]
|
||||||
|
ipcMain.on(cancelDownloadLoadingFileList, (_evt: IpcMainEvent, token: string) => {
|
||||||
|
if (token === cancelToken) {
|
||||||
|
cancelTask[0] = true
|
||||||
|
ipcMain.removeAllListeners(cancelDownloadLoadingFileList)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
let res = {} as any
|
||||||
|
const result = {
|
||||||
|
fullList: <any>[],
|
||||||
|
success: false,
|
||||||
|
finished: false
|
||||||
|
}
|
||||||
|
const config = new qiniu.conf.Config()
|
||||||
|
const bucketManager = new qiniu.rs.BucketManager(this.mac, config)
|
||||||
|
do {
|
||||||
|
res = await new Promise((resolve, reject) => {
|
||||||
|
bucketManager.listPrefix(bucket, {
|
||||||
|
prefix: slicedPrefix === '' ? undefined : slicedPrefix,
|
||||||
|
marker,
|
||||||
|
limit: 1000
|
||||||
|
}, (err: any, respBody: any, respInfo: any) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err)
|
||||||
|
} else {
|
||||||
|
resolve({
|
||||||
|
respBody,
|
||||||
|
respInfo
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
if (res && res.respInfo.statusCode === 200) {
|
||||||
|
res.respBody && res.respBody.items && res.respBody.items.forEach((item: any) => {
|
||||||
|
item.fsize !== 0 && result.fullList.push(this.formatFile(item, slicedPrefix, urlPrefix))
|
||||||
|
})
|
||||||
|
window.webContents.send(refreshDownloadFileTransferList, result)
|
||||||
|
} else {
|
||||||
|
result.finished = true
|
||||||
|
window.webContents.send(refreshDownloadFileTransferList, result)
|
||||||
|
ipcMain.removeAllListeners(cancelDownloadLoadingFileList)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
marker = res.respBody.marker
|
||||||
|
} while (res.respBody && res.respBody.marker && !cancelTask[0])
|
||||||
|
result.success = !cancelTask[0]
|
||||||
|
result.finished = true
|
||||||
|
window.webContents.send(refreshDownloadFileTransferList, result)
|
||||||
|
ipcMain.removeAllListeners(cancelDownloadLoadingFileList)
|
||||||
|
}
|
||||||
|
|
||||||
async getBucketListBackstage (configMap: IStringKeyMap): Promise<any> {
|
async getBucketListBackstage (configMap: IStringKeyMap): Promise<any> {
|
||||||
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
const { bucketName: bucket, prefix, cancelToken, customUrl: urlPrefix } = configMap
|
const { bucketName: bucket, prefix, cancelToken, customUrl: urlPrefix } = configMap
|
||||||
@@ -300,7 +357,7 @@ class QiniuApi {
|
|||||||
}
|
}
|
||||||
marker = res.respBody.marker
|
marker = res.respBody.marker
|
||||||
} while (res.respBody && res.respBody.marker && !cancelTask[0])
|
} while (res.respBody && res.respBody.marker && !cancelTask[0])
|
||||||
result.success = true
|
result.success = !cancelTask[0]
|
||||||
result.finished = true
|
result.finished = true
|
||||||
window.webContents.send('refreshFileTransferList', result)
|
window.webContents.send('refreshFileTransferList', result)
|
||||||
ipcMain.removeAllListeners('cancelLoadingFileList')
|
ipcMain.removeAllListeners('cancelLoadingFileList')
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import UpDownTaskQueue,
|
|||||||
} from '../datastore/upDownTaskQueue'
|
} from '../datastore/upDownTaskQueue'
|
||||||
import fs from 'fs-extra'
|
import fs from 'fs-extra'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
|
import { cancelDownloadLoadingFileList, refreshDownloadFileTransferList } from '@/manage/utils/static'
|
||||||
|
|
||||||
interface S3plistApiOptions {
|
interface S3plistApiOptions {
|
||||||
credentials: {
|
credentials: {
|
||||||
@@ -129,9 +130,9 @@ class S3plistApi {
|
|||||||
*/
|
*/
|
||||||
async getBucketList (): Promise<any> {
|
async getBucketList (): Promise<any> {
|
||||||
const options = Object.assign({}, this.baseOptions) as S3ClientConfig
|
const options = Object.assign({}, this.baseOptions) as S3ClientConfig
|
||||||
options.region = 'us-east-1'
|
|
||||||
const result = [] as IStringKeyMap[]
|
const result = [] as IStringKeyMap[]
|
||||||
const endpoint = options.endpoint as string || '' as string
|
const endpoint = options.endpoint as string || '' as string
|
||||||
|
options.region = endpoint.indexOf('cloudflarestorage') !== -1 ? 'auto' : 'us-east-1'
|
||||||
try {
|
try {
|
||||||
const client = new S3Client(options)
|
const client = new S3Client(options)
|
||||||
const command = new ListBucketsCommand({})
|
const command = new ListBucketsCommand({})
|
||||||
@@ -180,6 +181,64 @@ class S3plistApi {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getBucketListRecursively (configMap: IStringKeyMap): Promise<any> {
|
||||||
|
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
|
const { bucketName: bucket, bucketConfig: { Location: region }, prefix, cancelToken } = configMap
|
||||||
|
const slicedPrefix = prefix.slice(1)
|
||||||
|
const urlPrefix = configMap.customUrl || `https://${bucket}.s3.amazonaws.com`
|
||||||
|
let marker
|
||||||
|
const cancelTask = [false]
|
||||||
|
ipcMain.on(cancelDownloadLoadingFileList, (_evt: IpcMainEvent, token: string) => {
|
||||||
|
if (token === cancelToken) {
|
||||||
|
cancelTask[0] = true
|
||||||
|
ipcMain.removeAllListeners(cancelDownloadLoadingFileList)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
let res = {} as ListObjectsV2CommandOutput
|
||||||
|
const result = {
|
||||||
|
fullList: <any>[],
|
||||||
|
success: false,
|
||||||
|
finished: false
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
do {
|
||||||
|
const options = Object.assign({}, this.baseOptions) as S3ClientConfig
|
||||||
|
options.region = region || 'us-east-1'
|
||||||
|
const client = new S3Client(options)
|
||||||
|
const command = new ListObjectsV2Command({
|
||||||
|
Bucket: bucket,
|
||||||
|
Prefix: slicedPrefix === '' ? undefined : slicedPrefix,
|
||||||
|
MaxKeys: 1000,
|
||||||
|
ContinuationToken: marker
|
||||||
|
})
|
||||||
|
res = await client.send(command)
|
||||||
|
if (res.$metadata.httpStatusCode === 200) {
|
||||||
|
res.Contents && res.Contents.forEach((item: _Object) => {
|
||||||
|
result.fullList.push(this.formatFile(item, slicedPrefix, urlPrefix))
|
||||||
|
})
|
||||||
|
window.webContents.send(refreshDownloadFileTransferList, result)
|
||||||
|
} else {
|
||||||
|
this.logParam(res, 'getBucketListRecursively')
|
||||||
|
result.finished = true
|
||||||
|
window.webContents.send(refreshDownloadFileTransferList, result)
|
||||||
|
ipcMain.removeAllListeners(cancelDownloadLoadingFileList)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
marker = res.NextContinuationToken
|
||||||
|
} while (res.IsTruncated && !cancelTask[0])
|
||||||
|
} catch (error) {
|
||||||
|
this.logParam(error, 'getBucketListRecursively')
|
||||||
|
result.finished = true
|
||||||
|
window.webContents.send(refreshDownloadFileTransferList, result)
|
||||||
|
ipcMain.removeAllListeners(cancelDownloadLoadingFileList)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
result.success = !cancelTask[0]
|
||||||
|
result.finished = true
|
||||||
|
window.webContents.send(refreshDownloadFileTransferList, result)
|
||||||
|
ipcMain.removeAllListeners(cancelDownloadLoadingFileList)
|
||||||
|
}
|
||||||
|
|
||||||
async getBucketListBackstage (configMap: IStringKeyMap): Promise<any> {
|
async getBucketListBackstage (configMap: IStringKeyMap): Promise<any> {
|
||||||
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
const { bucketName: bucket, bucketConfig: { Location: region }, prefix, cancelToken } = configMap
|
const { bucketName: bucket, bucketConfig: { Location: region }, prefix, cancelToken } = configMap
|
||||||
@@ -221,7 +280,7 @@ class S3plistApi {
|
|||||||
})
|
})
|
||||||
window.webContents.send('refreshFileTransferList', result)
|
window.webContents.send('refreshFileTransferList', result)
|
||||||
} else {
|
} else {
|
||||||
this.logParam(res, 'getBucketFileList')
|
this.logParam(res, 'getBucketListBackstage')
|
||||||
result.finished = true
|
result.finished = true
|
||||||
window.webContents.send('refreshFileTransferList', result)
|
window.webContents.send('refreshFileTransferList', result)
|
||||||
ipcMain.removeAllListeners('cancelLoadingFileList')
|
ipcMain.removeAllListeners('cancelLoadingFileList')
|
||||||
@@ -230,12 +289,13 @@ class S3plistApi {
|
|||||||
marker = res.NextContinuationToken
|
marker = res.NextContinuationToken
|
||||||
} while (res.IsTruncated && !cancelTask[0])
|
} while (res.IsTruncated && !cancelTask[0])
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logParam(error, 'getBucketFileList')
|
this.logParam(error, 'getBucketListBackstage')
|
||||||
result.finished = true
|
result.finished = true
|
||||||
window.webContents.send('refreshFileTransferList', result)
|
window.webContents.send('refreshFileTransferList', result)
|
||||||
ipcMain.removeAllListeners('cancelLoadingFileList')
|
ipcMain.removeAllListeners('cancelLoadingFileList')
|
||||||
|
return
|
||||||
}
|
}
|
||||||
result.success = true
|
result.success = !cancelTask[0]
|
||||||
result.finished = true
|
result.finished = true
|
||||||
window.webContents.send('refreshFileTransferList', result)
|
window.webContents.send('refreshFileTransferList', result)
|
||||||
ipcMain.removeAllListeners('cancelLoadingFileList')
|
ipcMain.removeAllListeners('cancelLoadingFileList')
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ class SmmsApi {
|
|||||||
}
|
}
|
||||||
marker++
|
marker++
|
||||||
} while (!cancelTask[0] && res && res.status === 200 && res.data && res.data.success && res.data.CurrentPage < res.data.TotalPages)
|
} while (!cancelTask[0] && res && res.status === 200 && res.data && res.data.success && res.data.CurrentPage < res.data.TotalPages)
|
||||||
result.success = true
|
result.success = !cancelTask[0]
|
||||||
result.finished = true
|
result.finished = true
|
||||||
window.webContents.send('refreshFileTransferList', result)
|
window.webContents.send('refreshFileTransferList', result)
|
||||||
ipcMain.removeAllListeners('cancelLoadingFileList')
|
ipcMain.removeAllListeners('cancelLoadingFileList')
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import UpDownTaskQueue,
|
|||||||
downloadTaskSpecialStatus
|
downloadTaskSpecialStatus
|
||||||
} from '../datastore/upDownTaskQueue'
|
} from '../datastore/upDownTaskQueue'
|
||||||
import { ManageLogger } from '../utils/logger'
|
import { ManageLogger } from '../utils/logger'
|
||||||
|
import { cancelDownloadLoadingFileList, refreshDownloadFileTransferList } from '@/manage/utils/static'
|
||||||
|
|
||||||
class TcyunApi {
|
class TcyunApi {
|
||||||
ctx: COS
|
ctx: COS
|
||||||
@@ -115,6 +116,53 @@ class TcyunApi {
|
|||||||
return res && res.statusCode === 200
|
return res && res.statusCode === 200
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getBucketListRecursively (configMap: IStringKeyMap): Promise<any> {
|
||||||
|
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
|
const bucket = configMap.bucketName
|
||||||
|
const region = configMap.bucketConfig.Location
|
||||||
|
const prefix = configMap.prefix as string
|
||||||
|
const slicedPrefix = prefix.slice(1, prefix.length)
|
||||||
|
const urlPrefix = configMap.customUrl || `https://${bucket}.cos.${region}.myqcloud.com`
|
||||||
|
let marker
|
||||||
|
const cancelToken = configMap.cancelToken as string
|
||||||
|
const cancelTask = [false]
|
||||||
|
ipcMain.on(cancelDownloadLoadingFileList, (_evt: IpcMainEvent, token: string) => {
|
||||||
|
if (token === cancelToken) {
|
||||||
|
cancelTask[0] = true
|
||||||
|
ipcMain.removeAllListeners(cancelDownloadLoadingFileList)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
let res = {} as COS.GetBucketResult
|
||||||
|
const result = {
|
||||||
|
fullList: <any>[],
|
||||||
|
success: false,
|
||||||
|
finished: false
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
res = await this.ctx.getBucket({
|
||||||
|
Bucket: bucket,
|
||||||
|
Region: region,
|
||||||
|
Prefix: slicedPrefix === '' ? undefined : slicedPrefix,
|
||||||
|
Marker: marker
|
||||||
|
})
|
||||||
|
if (res && res.statusCode === 200) {
|
||||||
|
res.Contents.forEach((item: COS.CosObject) =>
|
||||||
|
parseInt(item.Size) !== 0 && result.fullList.push(this.formatFile(item, slicedPrefix, urlPrefix)))
|
||||||
|
window.webContents.send(refreshDownloadFileTransferList, result)
|
||||||
|
} else {
|
||||||
|
result.finished = true
|
||||||
|
window.webContents.send(refreshDownloadFileTransferList, result)
|
||||||
|
ipcMain.removeAllListeners(cancelDownloadLoadingFileList)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
marker = res.NextMarker
|
||||||
|
} while (res.IsTruncated === 'true' && !cancelTask[0])
|
||||||
|
result.success = !cancelTask[0]
|
||||||
|
result.finished = true
|
||||||
|
window.webContents.send(refreshDownloadFileTransferList, result)
|
||||||
|
ipcMain.removeAllListeners(cancelDownloadLoadingFileList)
|
||||||
|
}
|
||||||
|
|
||||||
async getBucketListBackstage (configMap: IStringKeyMap): Promise < any > {
|
async getBucketListBackstage (configMap: IStringKeyMap): Promise < any > {
|
||||||
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
const bucket = configMap.bucketName
|
const bucket = configMap.bucketName
|
||||||
@@ -159,7 +207,7 @@ class TcyunApi {
|
|||||||
}
|
}
|
||||||
marker = res.NextMarker
|
marker = res.NextMarker
|
||||||
} while (res.IsTruncated === 'true' && !cancelTask[0])
|
} while (res.IsTruncated === 'true' && !cancelTask[0])
|
||||||
result.success = true
|
result.success = !cancelTask[0]
|
||||||
result.finished = true
|
result.finished = true
|
||||||
window.webContents.send('refreshFileTransferList', result)
|
window.webContents.send('refreshFileTransferList', result)
|
||||||
ipcMain.removeAllListeners('cancelLoadingFileList')
|
ipcMain.removeAllListeners('cancelLoadingFileList')
|
||||||
@@ -481,6 +529,7 @@ class TcyunApi {
|
|||||||
sourceFileName: fileName,
|
sourceFileName: fileName,
|
||||||
targetFilePath: path.join(downloadPath, fileName)
|
targetFilePath: path.join(downloadPath, fileName)
|
||||||
})
|
})
|
||||||
|
fs.ensureDirSync(path.dirname(path.join(downloadPath, fileName)))
|
||||||
this.ctx.downloadFile({
|
this.ctx.downloadFile({
|
||||||
Bucket: bucketName,
|
Bucket: bucketName,
|
||||||
Region: region,
|
Region: region,
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import UpDownTaskQueue,
|
|||||||
commonTaskStatus
|
commonTaskStatus
|
||||||
} from '../datastore/upDownTaskQueue'
|
} from '../datastore/upDownTaskQueue'
|
||||||
import { ManageLogger } from '../utils/logger'
|
import { ManageLogger } from '../utils/logger'
|
||||||
|
import { cancelDownloadLoadingFileList, refreshDownloadFileTransferList } from '@/manage/utils/static'
|
||||||
|
|
||||||
class UpyunApi {
|
class UpyunApi {
|
||||||
ser: Upyun.Service
|
ser: Upyun.Service
|
||||||
@@ -91,6 +92,58 @@ class UpyunApi {
|
|||||||
return this.bucket
|
return this.bucket
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getBucketListRecursively (configMap: IStringKeyMap): Promise<any> {
|
||||||
|
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
|
const { bucketName: bucket, prefix, cancelToken } = configMap
|
||||||
|
const slicedPrefix = prefix.slice(1)
|
||||||
|
const urlPrefix = configMap.customUrl || `http://${bucket}.test.upcdn.net`
|
||||||
|
const cancelTask = [false]
|
||||||
|
ipcMain.on(cancelDownloadLoadingFileList, (_evt: IpcMainEvent, token: string) => {
|
||||||
|
if (token === cancelToken) {
|
||||||
|
cancelTask[0] = true
|
||||||
|
ipcMain.removeAllListeners(cancelDownloadLoadingFileList)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
let res = {} as any
|
||||||
|
const result = {
|
||||||
|
fullList: <any>[],
|
||||||
|
success: false,
|
||||||
|
finished: false
|
||||||
|
}
|
||||||
|
const folderQueue = [prefix]
|
||||||
|
const getFolderFile = async (folder: any) => {
|
||||||
|
let marker = ''
|
||||||
|
const key = folder
|
||||||
|
do {
|
||||||
|
res = await this.cli.listDir(key, {
|
||||||
|
limit: 10000,
|
||||||
|
iter: marker
|
||||||
|
})
|
||||||
|
if (res) {
|
||||||
|
res.files && res.files.forEach((item: any) => {
|
||||||
|
item.type === 'F' && folderQueue.push(`${slicedPrefix}${item.name}/`)
|
||||||
|
item.type === 'N' && result.fullList.push(this.formatFile(item, folder, urlPrefix))
|
||||||
|
})
|
||||||
|
window.webContents.send(refreshDownloadFileTransferList, result)
|
||||||
|
} else {
|
||||||
|
result.finished = true
|
||||||
|
window.webContents.send(refreshDownloadFileTransferList, result)
|
||||||
|
ipcMain.removeAllListeners(cancelDownloadLoadingFileList)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
marker = res.next
|
||||||
|
} while (!cancelTask[0] && res.next !== this.stopMarker)
|
||||||
|
}
|
||||||
|
while (folderQueue.length) {
|
||||||
|
const folder = folderQueue.shift()
|
||||||
|
await getFolderFile(folder)
|
||||||
|
}
|
||||||
|
result.success = !cancelTask[0]
|
||||||
|
result.finished = true
|
||||||
|
window.webContents.send(refreshDownloadFileTransferList, result)
|
||||||
|
ipcMain.removeAllListeners(cancelDownloadLoadingFileList)
|
||||||
|
}
|
||||||
|
|
||||||
async getBucketListBackstage (configMap: IStringKeyMap): Promise<any> {
|
async getBucketListBackstage (configMap: IStringKeyMap): Promise<any> {
|
||||||
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
const { bucketName: bucket, prefix, cancelToken } = configMap
|
const { bucketName: bucket, prefix, cancelToken } = configMap
|
||||||
@@ -129,7 +182,7 @@ class UpyunApi {
|
|||||||
}
|
}
|
||||||
marker = res.next
|
marker = res.next
|
||||||
} while (!cancelTask[0] && res.next !== this.stopMarker)
|
} while (!cancelTask[0] && res.next !== this.stopMarker)
|
||||||
result.success = true
|
result.success = !cancelTask[0]
|
||||||
result.finished = true
|
result.finished = true
|
||||||
window.webContents.send('refreshFileTransferList', result)
|
window.webContents.send('refreshFileTransferList', result)
|
||||||
ipcMain.removeAllListeners('cancelLoadingFileList')
|
ipcMain.removeAllListeners('cancelLoadingFileList')
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import UpDownTaskQueue,
|
|||||||
} from '../datastore/upDownTaskQueue'
|
} from '../datastore/upDownTaskQueue'
|
||||||
import fs from 'fs-extra'
|
import fs from 'fs-extra'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
|
import { cancelDownloadLoadingFileList, refreshDownloadFileTransferList } from '@/manage/utils/static'
|
||||||
|
|
||||||
class WebdavplistApi {
|
class WebdavplistApi {
|
||||||
endpoint: string
|
endpoint: string
|
||||||
@@ -85,6 +86,55 @@ class WebdavplistApi {
|
|||||||
|
|
||||||
isRequestSuccess = (code: number) => code >= 200 && code < 300
|
isRequestSuccess = (code: number) => code >= 200 && code < 300
|
||||||
|
|
||||||
|
async getBucketListRecursively (configMap: IStringKeyMap): Promise<any> {
|
||||||
|
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
|
const { prefix, customUrl, cancelToken } = configMap
|
||||||
|
const urlPrefix = customUrl || this.endpoint
|
||||||
|
const cancelTask = [false]
|
||||||
|
ipcMain.on(cancelDownloadLoadingFileList, (_evt: IpcMainEvent, token: string) => {
|
||||||
|
if (token === cancelToken) {
|
||||||
|
cancelTask[0] = true
|
||||||
|
ipcMain.removeAllListeners(cancelDownloadLoadingFileList)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
let res = {} as any
|
||||||
|
const result = {
|
||||||
|
fullList: <any>[],
|
||||||
|
success: false,
|
||||||
|
finished: false
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
res = await this.ctx.getDirectoryContents(prefix, {
|
||||||
|
deep: true,
|
||||||
|
details: true
|
||||||
|
})
|
||||||
|
if (this.isRequestSuccess(res.status)) {
|
||||||
|
if (res.data && res.data.length) {
|
||||||
|
res.data.forEach((item: FileStat) => {
|
||||||
|
if (item.type !== 'directory') {
|
||||||
|
result.fullList.push(this.formatFile(item, urlPrefix))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result.finished = true
|
||||||
|
window.webContents.send(refreshDownloadFileTransferList, result)
|
||||||
|
ipcMain.removeAllListeners(cancelDownloadLoadingFileList)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
this.logParam(error, 'getBucketListRecursively')
|
||||||
|
result.finished = true
|
||||||
|
window.webContents.send(refreshDownloadFileTransferList, result)
|
||||||
|
ipcMain.removeAllListeners(cancelDownloadLoadingFileList)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
result.success = true
|
||||||
|
result.finished = true
|
||||||
|
window.webContents.send(refreshDownloadFileTransferList, result)
|
||||||
|
ipcMain.removeAllListeners(cancelDownloadLoadingFileList)
|
||||||
|
}
|
||||||
|
|
||||||
async getBucketListBackstage (configMap: IStringKeyMap): Promise<any> {
|
async getBucketListBackstage (configMap: IStringKeyMap): Promise<any> {
|
||||||
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
const window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
const { prefix, customUrl, cancelToken } = configMap
|
const { prefix, customUrl, cancelToken } = configMap
|
||||||
@@ -128,6 +178,7 @@ class WebdavplistApi {
|
|||||||
result.finished = true
|
result.finished = true
|
||||||
window.webContents.send('refreshFileTransferList', result)
|
window.webContents.send('refreshFileTransferList', result)
|
||||||
ipcMain.removeAllListeners('cancelLoadingFileList')
|
ipcMain.removeAllListeners('cancelLoadingFileList')
|
||||||
|
return
|
||||||
}
|
}
|
||||||
result.success = true
|
result.success = true
|
||||||
result.finished = true
|
result.finished = true
|
||||||
|
|||||||
@@ -56,6 +56,11 @@ export const manageIpcList = {
|
|||||||
return manage.getBucketListBackstage(param)
|
return manage.getBucketListBackstage(param)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
ipcMain.on('getBucketListRecursively', async (_evt: IpcMainInvokeEvent, currentPicBed: string, param: IStringKeyMap) => {
|
||||||
|
const manage = new ManageApi(currentPicBed)
|
||||||
|
return manage.getBucketListRecursively(param)
|
||||||
|
})
|
||||||
|
|
||||||
ipcMain.handle('openFileSelectDialog', async () => {
|
ipcMain.handle('openFileSelectDialog', async () => {
|
||||||
const res = await dialog.showOpenDialog({
|
const res = await dialog.showOpenDialog({
|
||||||
properties: ['openFile', 'multiSelections']
|
properties: ['openFile', 'multiSelections']
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import API from './apis/api'
|
|||||||
import windowManager from 'apis/app/window/windowManager'
|
import windowManager from 'apis/app/window/windowManager'
|
||||||
import { IWindowList } from '#/types/enum'
|
import { IWindowList } from '#/types/enum'
|
||||||
import { ipcMain } from 'electron'
|
import { ipcMain } from 'electron'
|
||||||
|
import { cancelDownloadLoadingFileList, refreshDownloadFileTransferList } from '@/manage/utils/static'
|
||||||
|
|
||||||
export class ManageApi extends EventEmitter implements ManageApiType {
|
export class ManageApi extends EventEmitter implements ManageApiType {
|
||||||
private _config!: Partial<ManageConfigType>
|
private _config!: Partial<ManageConfigType>
|
||||||
@@ -293,6 +294,44 @@ export class ManageApi extends EventEmitter implements ManageApiType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getBucketListRecursively (
|
||||||
|
param?: IStringKeyMap
|
||||||
|
): Promise<IStringKeyMap | ManageError> {
|
||||||
|
let client
|
||||||
|
let window
|
||||||
|
const defaultResult = {
|
||||||
|
fullList: [],
|
||||||
|
success: false,
|
||||||
|
finished: true
|
||||||
|
}
|
||||||
|
switch (this.currentPicBedConfig.picBedName) {
|
||||||
|
case 'tcyun':
|
||||||
|
case 'aliyun':
|
||||||
|
case 'qiniu':
|
||||||
|
case 'upyun':
|
||||||
|
case 'smms':
|
||||||
|
case 'github':
|
||||||
|
case 'imgur':
|
||||||
|
case 's3plist':
|
||||||
|
case 'webdavplist':
|
||||||
|
try {
|
||||||
|
client = this.createClient() as any
|
||||||
|
return await client.getBucketListRecursively(param!)
|
||||||
|
} catch (error: any) {
|
||||||
|
this.errorMsg(error, this.getMsgParam('getBucketListRecursively'))
|
||||||
|
window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
|
window.webContents.send(refreshDownloadFileTransferList, defaultResult)
|
||||||
|
ipcMain.removeAllListeners(cancelDownloadLoadingFileList)
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
window = windowManager.get(IWindowList.SETTING_WINDOW)!
|
||||||
|
window.webContents.send(refreshDownloadFileTransferList, defaultResult)
|
||||||
|
ipcMain.removeAllListeners(cancelDownloadLoadingFileList)
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 后台更新bucket文件列表
|
* 后台更新bucket文件列表
|
||||||
* @param param
|
* @param param
|
||||||
|
|||||||
@@ -286,6 +286,7 @@ ea/*
|
|||||||
size="small"
|
size="small"
|
||||||
type="primary"
|
type="primary"
|
||||||
plain
|
plain
|
||||||
|
style="margin-right: 2px;"
|
||||||
@click="handleCheckAllChange"
|
@click="handleCheckAllChange"
|
||||||
>
|
>
|
||||||
全选
|
全选
|
||||||
@@ -300,6 +301,7 @@ ea/*
|
|||||||
size="small"
|
size="small"
|
||||||
type="warning"
|
type="warning"
|
||||||
plain
|
plain
|
||||||
|
style="margin-right: 2px;"
|
||||||
@click="handelCancelCheck"
|
@click="handelCancelCheck"
|
||||||
>
|
>
|
||||||
取消
|
取消
|
||||||
@@ -309,6 +311,7 @@ ea/*
|
|||||||
size="small"
|
size="small"
|
||||||
type="primary"
|
type="primary"
|
||||||
plain
|
plain
|
||||||
|
style="margin-right: 2px;"
|
||||||
@click="handleReverseCheck"
|
@click="handleReverseCheck"
|
||||||
>
|
>
|
||||||
反选
|
反选
|
||||||
@@ -318,6 +321,7 @@ ea/*
|
|||||||
size="small"
|
size="small"
|
||||||
type="primary"
|
type="primary"
|
||||||
plain
|
plain
|
||||||
|
style="margin-right: 2px;"
|
||||||
@click="handleCheckAllChange"
|
@click="handleCheckAllChange"
|
||||||
>
|
>
|
||||||
全选
|
全选
|
||||||
@@ -328,9 +332,10 @@ ea/*
|
|||||||
type="success"
|
type="success"
|
||||||
plain
|
plain
|
||||||
:icon="Download"
|
:icon="Download"
|
||||||
|
style="margin-right: 2px;"
|
||||||
@click="handelBatchDownload"
|
@click="handelBatchDownload"
|
||||||
>
|
>
|
||||||
下载({{ selectedItems.length }})
|
下载({{ selectedItems.filter(item => item.isDir === false).length }})
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
class="btn"
|
class="btn"
|
||||||
@@ -532,7 +537,7 @@ https://www.baidu.com/img/bd_logo1.png"
|
|||||||
>
|
>
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-icon
|
<el-icon
|
||||||
v-if="!item.isDir || !showRenameFileIcon"
|
v-if="!item.isDir && showRenameFileIcon"
|
||||||
size="20"
|
size="20"
|
||||||
style="cursor: pointer;"
|
style="cursor: pointer;"
|
||||||
color="#409EFF"
|
color="#409EFF"
|
||||||
@@ -540,6 +545,15 @@ https://www.baidu.com/img/bd_logo1.png"
|
|||||||
>
|
>
|
||||||
<Edit />
|
<Edit />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
|
<el-icon
|
||||||
|
v-if="item.isDir"
|
||||||
|
size="20"
|
||||||
|
style="cursor: pointer;"
|
||||||
|
color="crimson"
|
||||||
|
@click="handelFolderBatchDownload(item)"
|
||||||
|
>
|
||||||
|
<Download />
|
||||||
|
</el-icon>
|
||||||
<el-dropdown>
|
<el-dropdown>
|
||||||
<template #default>
|
<template #default>
|
||||||
<el-icon
|
<el-icon
|
||||||
@@ -687,20 +701,34 @@ https://www.baidu.com/img/bd_logo1.png"
|
|||||||
加载中,点击取消
|
加载中,点击取消
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-affix>
|
</el-affix>
|
||||||
|
<el-affix
|
||||||
|
v-if="isLoadingDownloadData"
|
||||||
|
style="position: fixed;top: 50px;right: 0px;"
|
||||||
|
@click="cancelDownloadLoading"
|
||||||
|
>
|
||||||
|
<el-button
|
||||||
|
type="warning"
|
||||||
|
icon="el-icon-loading"
|
||||||
|
style="font-size: 12px;font-weight: 500;"
|
||||||
|
:loading="isLoadingDownloadData"
|
||||||
|
>
|
||||||
|
准备下载中,点击取消
|
||||||
|
</el-button>
|
||||||
|
</el-affix>
|
||||||
<el-drawer
|
<el-drawer
|
||||||
v-model="isShowUploadPanel"
|
v-model="isShowUploadPanel"
|
||||||
size="60%"
|
size="60%"
|
||||||
@open="startRefreshUploadTask"
|
@open="startRefreshUploadTask"
|
||||||
@close="stopRefreshUploadTask"
|
@close="stopRefreshUploadTask"
|
||||||
>
|
>
|
||||||
<template #header>
|
<template #header>
|
||||||
<el-switch
|
<el-switch
|
||||||
v-model="isUploadKeepDirStructure"
|
v-model="isUploadKeepDirStructure"
|
||||||
@change="handleUploadKeepDirChange"
|
active-text="保持目录结构"
|
||||||
active-text="保持目录结构"
|
inactive-text="不保持目录结构"
|
||||||
inactive-text="不保持目录结构"
|
@change="handleUploadKeepDirChange"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<div
|
<div
|
||||||
id="upload-area"
|
id="upload-area"
|
||||||
:class="{ 'is-dragover': dragover }"
|
:class="{ 'is-dragover': dragover }"
|
||||||
@@ -1204,6 +1232,7 @@ import { useRoute } from 'vue-router'
|
|||||||
import { Grid, Fold, Close, Folder, FolderAdd, Upload, CircleClose, Loading, CopyDocument, Edit, DocumentAdd, Link, Refresh, ArrowRight, HomeFilled, Document, Coin, Download, DeleteFilled, Sort, FolderOpened } from '@element-plus/icons-vue'
|
import { Grid, Fold, Close, Folder, FolderAdd, Upload, CircleClose, Loading, CopyDocument, Edit, DocumentAdd, Link, Refresh, ArrowRight, HomeFilled, Document, Coin, Download, DeleteFilled, Sort, FolderOpened } from '@element-plus/icons-vue'
|
||||||
import { useManageStore } from '../store/manageStore'
|
import { useManageStore } from '../store/manageStore'
|
||||||
import { renameFile, formatLink, formatFileName, getFileIconPath, formatFileSize, getExtension, isValidUrl, svg } from '../utils/common'
|
import { renameFile, formatLink, formatFileName, getFileIconPath, formatFileSize, getExtension, isValidUrl, svg } from '../utils/common'
|
||||||
|
import { cancelDownloadLoadingFileList, refreshDownloadFileTransferList } from '../utils/static'
|
||||||
import { ipcRenderer, clipboard, IpcRendererEvent } from 'electron'
|
import { ipcRenderer, clipboard, IpcRendererEvent } from 'electron'
|
||||||
import { fileCacheDbInstance } from '../store/bucketFileDb'
|
import { fileCacheDbInstance } from '../store/bucketFileDb'
|
||||||
import { trimPath } from '~/main/manage/utils/common'
|
import { trimPath } from '~/main/manage/utils/common'
|
||||||
@@ -1225,7 +1254,7 @@ import {
|
|||||||
ElCard
|
ElCard
|
||||||
} from 'element-plus'
|
} from 'element-plus'
|
||||||
import type { Column, RowClassNameGetter } from 'element-plus'
|
import type { Column, RowClassNameGetter } from 'element-plus'
|
||||||
import { useFileTransferStore } from '@/manage/store/manageStore'
|
import { useFileTransferStore, useDownloadFileTransferStore } from '@/manage/store/manageStore'
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import { IUploadTask, IDownloadTask } from '~/main/manage/datastore/upDownTaskQueue'
|
import { IUploadTask, IDownloadTask } from '~/main/manage/datastore/upDownTaskQueue'
|
||||||
@@ -1267,6 +1296,7 @@ const fileSortTimeReverse = ref(false)
|
|||||||
const fileSortSizeReverse = ref(false)
|
const fileSortSizeReverse = ref(false)
|
||||||
const fileSortExtReverse = ref(false)
|
const fileSortExtReverse = ref(false)
|
||||||
const currentPageFilesInfo = reactive([] as any[])
|
const currentPageFilesInfo = reactive([] as any[])
|
||||||
|
const currentDownloadFileList = reactive([] as any[])
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const configMap = reactive(JSON.parse(route.query.configMap as string))
|
const configMap = reactive(JSON.parse(route.query.configMap as string))
|
||||||
const selectedItems = reactive([] as any[])
|
const selectedItems = reactive([] as any[])
|
||||||
@@ -1282,7 +1312,9 @@ const elTable = ref(null as any)
|
|||||||
const isShiftKeyPress = ref<boolean>(false)
|
const isShiftKeyPress = ref<boolean>(false)
|
||||||
const lastChoosed = ref<number>(-1)
|
const lastChoosed = ref<number>(-1)
|
||||||
const isLoadingData = ref(false)
|
const isLoadingData = ref(false)
|
||||||
|
const isLoadingDownloadData = ref(false)
|
||||||
const cancelToken = ref('')
|
const cancelToken = ref('')
|
||||||
|
const downloadCancelToken = ref('')
|
||||||
const isShowUploadPanel = ref(false)
|
const isShowUploadPanel = ref(false)
|
||||||
const isShowDownloadPanel = ref(false)
|
const isShowDownloadPanel = ref(false)
|
||||||
const dragover = ref(false)
|
const dragover = ref(false)
|
||||||
@@ -1823,11 +1855,16 @@ async function resetParam (force: boolean = false) {
|
|||||||
isLoadingData.value = false
|
isLoadingData.value = false
|
||||||
ipcRenderer.send('cancelLoadingFileList', cancelToken.value)
|
ipcRenderer.send('cancelLoadingFileList', cancelToken.value)
|
||||||
}
|
}
|
||||||
|
if (isLoadingDownloadData.value) {
|
||||||
|
isLoadingDownloadData.value = false
|
||||||
|
ipcRenderer.send(cancelDownloadLoadingFileList, downloadCancelToken.value)
|
||||||
|
}
|
||||||
cancelToken.value = ''
|
cancelToken.value = ''
|
||||||
pagingMarker.value = ''
|
pagingMarker.value = ''
|
||||||
currentPrefix.value = configMap.prefix
|
currentPrefix.value = configMap.prefix
|
||||||
currentPage.value = 1
|
currentPage.value = 1
|
||||||
currentPageFilesInfo.length = 0
|
currentPageFilesInfo.length = 0
|
||||||
|
currentDownloadFileList.length = 0
|
||||||
selectedItems.length = 0
|
selectedItems.length = 0
|
||||||
searchText.value = ''
|
searchText.value = ''
|
||||||
urlToUpload.value = ''
|
urlToUpload.value = ''
|
||||||
@@ -2141,6 +2178,90 @@ function handleCheckChange (item: any) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function handelFolderBatchDownload (item: any) {
|
||||||
|
ElMessageBox.confirm('确定要下载该文件夹吗?', '提示', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
}).then(async () => {
|
||||||
|
const defaultDownloadPath = await ipcRenderer.invoke('getDefaultDownloadFolder')
|
||||||
|
const param = {
|
||||||
|
downloadPath: manageStore.config.settings.downloadDir ?? defaultDownloadPath,
|
||||||
|
maxDownloadFileCount: manageStore.config.settings.maxDownloadFileCount ? manageStore.config.settings.maxDownloadFileCount : 5,
|
||||||
|
fileArray: [] as any[]
|
||||||
|
}
|
||||||
|
cancelToken.value = uuidv4()
|
||||||
|
const paramGet = {
|
||||||
|
// tcyun
|
||||||
|
bucketName: configMap.bucketName,
|
||||||
|
bucketConfig: {
|
||||||
|
Location: configMap.bucketConfig.Location
|
||||||
|
},
|
||||||
|
paging: paging.value,
|
||||||
|
prefix: `/${item.key.replace(/\/+$/, '').replace(/^\/+/, '')}/`,
|
||||||
|
marker: pagingMarker.value,
|
||||||
|
itemsPerPage: itemsPerPage.value,
|
||||||
|
customUrl: currentCustomUrl.value,
|
||||||
|
currentPage: currentPage.value,
|
||||||
|
cancelToken: cancelToken.value,
|
||||||
|
cdnUrl: configMap.cdnUrl
|
||||||
|
}
|
||||||
|
isLoadingDownloadData.value = true
|
||||||
|
const downloadFileTransferStore = useDownloadFileTransferStore()
|
||||||
|
downloadFileTransferStore.resetDownloadFileTransferList()
|
||||||
|
ipcRenderer.send('getBucketListRecursively', configMap.alias, paramGet)
|
||||||
|
ipcRenderer.on(refreshDownloadFileTransferList, (evt: IpcRendererEvent, data) => {
|
||||||
|
downloadFileTransferStore.refreshDownloadFileTransferList(data)
|
||||||
|
})
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
const currentFileList = downloadFileTransferStore.getDownloadFileTransferList()
|
||||||
|
currentDownloadFileList.length = 0
|
||||||
|
currentDownloadFileList.push(...currentFileList)
|
||||||
|
if (downloadFileTransferStore.isFinished()) {
|
||||||
|
clearInterval(interval)
|
||||||
|
isLoadingDownloadData.value = false
|
||||||
|
if (downloadFileTransferStore.isSuccess()) {
|
||||||
|
ElNotification.success({
|
||||||
|
title: '提示',
|
||||||
|
message: '获取下载列表成功',
|
||||||
|
duration: 500
|
||||||
|
})
|
||||||
|
if (currentDownloadFileList.length) {
|
||||||
|
currentDownloadFileList.forEach((item: any) => {
|
||||||
|
param.fileArray.push({
|
||||||
|
alias: configMap.alias,
|
||||||
|
bucketName: configMap.bucketName,
|
||||||
|
region: configMap.bucketConfig.Location,
|
||||||
|
key: item.key,
|
||||||
|
fileName: [undefined, true].includes(manageStore.config.settings.isDownloadFolderKeepDirStructure) ? `/${item.key.replace(/\/+$/, '').replace(/^\/+/, '')}` : item.fileName,
|
||||||
|
customUrl: currentCustomUrl.value,
|
||||||
|
downloadUrl: item.downloadUrl,
|
||||||
|
githubUrl: item.url,
|
||||||
|
githubPrivate: configMap.bucketConfig.private
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
ipcRenderer.send('downloadBucketFile', configMap.alias, param)
|
||||||
|
isShowDownloadPanel.value = true
|
||||||
|
} else {
|
||||||
|
ElNotification.error({
|
||||||
|
title: '提示',
|
||||||
|
message: '获取失败',
|
||||||
|
duration: 500
|
||||||
|
})
|
||||||
|
}
|
||||||
|
downloadFileTransferStore.resetDownloadFileTransferList()
|
||||||
|
}
|
||||||
|
}, 500)
|
||||||
|
}).catch(() => {
|
||||||
|
ElNotification.info({
|
||||||
|
title: '提示',
|
||||||
|
message: '已取消',
|
||||||
|
duration: 500
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
async function handelBatchDownload () {
|
async function handelBatchDownload () {
|
||||||
const defaultDownloadPath = await ipcRenderer.invoke('getDefaultDownloadFolder')
|
const defaultDownloadPath = await ipcRenderer.invoke('getDefaultDownloadFolder')
|
||||||
const param = {
|
const param = {
|
||||||
@@ -2155,7 +2276,7 @@ async function handelBatchDownload () {
|
|||||||
bucketName: configMap.bucketName,
|
bucketName: configMap.bucketName,
|
||||||
region: configMap.bucketConfig.Location,
|
region: configMap.bucketConfig.Location,
|
||||||
key: item.key,
|
key: item.key,
|
||||||
fileName: item.fileName,
|
fileName: manageStore.config.settings.isDownloadFileKeepDirStructure ? `/${item.key.replace(/\/+$/, '').replace(/^\/+/, '')}` : item.fileName,
|
||||||
customUrl: currentCustomUrl.value,
|
customUrl: currentCustomUrl.value,
|
||||||
downloadUrl: item.downloadUrl,
|
downloadUrl: item.downloadUrl,
|
||||||
githubUrl: item.url,
|
githubUrl: item.url,
|
||||||
@@ -2313,6 +2434,18 @@ function cancelLoading () {
|
|||||||
}).catch(() => { })
|
}).catch(() => { })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function cancelDownloadLoading () {
|
||||||
|
ElMessageBox.confirm('是否停止下载文件获取?', '提示', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
}).then(() => {
|
||||||
|
isLoadingData.value = false
|
||||||
|
ipcRenderer.send(cancelDownloadLoadingFileList, downloadCancelToken.value)
|
||||||
|
ElMessage.success('下载文件获取已停止')
|
||||||
|
}).catch(() => { })
|
||||||
|
}
|
||||||
|
|
||||||
async function getBucketFileListBackStage () {
|
async function getBucketFileListBackStage () {
|
||||||
cancelToken.value = uuidv4()
|
cancelToken.value = uuidv4()
|
||||||
const param = {
|
const param = {
|
||||||
@@ -2364,13 +2497,13 @@ async function getBucketFileListBackStage () {
|
|||||||
ElNotification.success({
|
ElNotification.success({
|
||||||
title: '提示',
|
title: '提示',
|
||||||
message: '获取文件列表成功',
|
message: '获取文件列表成功',
|
||||||
duration: 1000
|
duration: 500
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
ElNotification.error({
|
ElNotification.error({
|
||||||
title: '提示',
|
title: '提示',
|
||||||
message: '部分文件获取失败',
|
message: '部分文件获取失败',
|
||||||
duration: 1000
|
duration: 500
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
fileTransferStore.resetFileTransferList()
|
fileTransferStore.resetFileTransferList()
|
||||||
@@ -2992,7 +3125,16 @@ const columns: Column<any>[] = [
|
|||||||
cellRenderer: ({ rowData: item }) => (
|
cellRenderer: ({ rowData: item }) => (
|
||||||
item.match || !searchText.value
|
item.match || !searchText.value
|
||||||
? item.isDir || !showRenameFileIcon.value
|
? item.isDir || !showRenameFileIcon.value
|
||||||
? <span></span>
|
? item.isDir
|
||||||
|
? <ElIcon
|
||||||
|
size="20"
|
||||||
|
style="cursor: pointer;"
|
||||||
|
color="#409EFF"
|
||||||
|
onClick={() => handelFolderBatchDownload(item)}
|
||||||
|
>
|
||||||
|
<Download />
|
||||||
|
</ElIcon>
|
||||||
|
: <template></template>
|
||||||
: <ElIcon
|
: <ElIcon
|
||||||
size="20"
|
size="20"
|
||||||
style="cursor: pointer;"
|
style="cursor: pointer;"
|
||||||
@@ -3178,7 +3320,11 @@ onBeforeUnmount(() => {
|
|||||||
if (isLoadingData.value) {
|
if (isLoadingData.value) {
|
||||||
ipcRenderer.send('cancelLoadingFileList', cancelToken.value)
|
ipcRenderer.send('cancelLoadingFileList', cancelToken.value)
|
||||||
}
|
}
|
||||||
|
if (isLoadingDownloadData.value) {
|
||||||
|
ipcRenderer.send(cancelDownloadLoadingFileList, downloadCancelToken.value)
|
||||||
|
}
|
||||||
ipcRenderer.removeAllListeners('refreshFileTransferList')
|
ipcRenderer.removeAllListeners('refreshFileTransferList')
|
||||||
|
ipcRenderer.removeAllListeners(refreshDownloadFileTransferList)
|
||||||
})
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -174,10 +174,10 @@
|
|||||||
<template #label>
|
<template #label>
|
||||||
<span
|
<span
|
||||||
style="position:absolute;left: 0;"
|
style="position:absolute;left: 0;"
|
||||||
>下载时保留目录结构
|
><span>下载</span><span style="color: orange;">文件</span><span>时保留目录结构</span>
|
||||||
<el-tooltip
|
<el-tooltip
|
||||||
effect="dark"
|
effect="dark"
|
||||||
content="开启后,下载文件时会保留目录结构,关闭后会将所有文件展开到下载目录下"
|
content="开启后,下载文件时会保留原始目录结构"
|
||||||
placement="right"
|
placement="right"
|
||||||
>
|
>
|
||||||
<el-icon>
|
<el-icon>
|
||||||
@@ -187,11 +187,35 @@
|
|||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
<el-switch
|
<el-switch
|
||||||
v-model="form.isDownloadKeepDirStructure"
|
v-model="form.isDownloadFileKeepDirStructure"
|
||||||
style="position:absolute;right: 0;"
|
style="position:absolute;right: 0;"
|
||||||
active-color="#13ce66"
|
active-color="#13ce66"
|
||||||
inactive-color="#ff4949"
|
inactive-color="#ff4949"
|
||||||
@change="handelIsDownloadKeepDirStructureChange"
|
@change="handelIsDownloadFileKeepDirStructureChange"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<template #label>
|
||||||
|
<span
|
||||||
|
style="position:absolute;left: 0;"
|
||||||
|
><span>下载</span><span style="color: coral;">文件夹</span><span>时保留目录结构</span>
|
||||||
|
<el-tooltip
|
||||||
|
effect="dark"
|
||||||
|
content="开启后,下载文件夹时会保留目录结构,关闭后会将所有文件展开到下载目录下"
|
||||||
|
placement="right"
|
||||||
|
>
|
||||||
|
<el-icon>
|
||||||
|
<InfoFilled />
|
||||||
|
</el-icon>
|
||||||
|
</el-tooltip>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<el-switch
|
||||||
|
v-model="form.isDownloadFolderKeepDirStructure"
|
||||||
|
style="position:absolute;right: 0;"
|
||||||
|
active-color="#13ce66"
|
||||||
|
inactive-color="#ff4949"
|
||||||
|
@change="handelIsDownloadFolderKeepDirStructureChange"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
@@ -499,7 +523,8 @@ const form = reactive<IStringKeyMap>({
|
|||||||
isForceCustomUrlHttps: false,
|
isForceCustomUrlHttps: false,
|
||||||
isShowList: false,
|
isShowList: false,
|
||||||
isUploadKeepDirStructure: true,
|
isUploadKeepDirStructure: true,
|
||||||
isDownloadKeepDirStructure: true
|
isDownloadFileKeepDirStructure: false,
|
||||||
|
isDownloadFolderKeepDirStructure: true
|
||||||
})
|
})
|
||||||
|
|
||||||
const downloadDir = ref('')
|
const downloadDir = ref('')
|
||||||
@@ -571,7 +596,8 @@ async function initData () {
|
|||||||
PreSignedExpire.value = config.settings.PreSignedExpire ?? 14400
|
PreSignedExpire.value = config.settings.PreSignedExpire ?? 14400
|
||||||
maxDownloadFileCount.value = config.settings.maxDownloadFileCount ?? 5
|
maxDownloadFileCount.value = config.settings.maxDownloadFileCount ?? 5
|
||||||
form.isUploadKeepDirStructure = config.settings.isUploadKeepDirStructure ?? true
|
form.isUploadKeepDirStructure = config.settings.isUploadKeepDirStructure ?? true
|
||||||
form.isDownloadKeepDirStructure = config.settings.isDownloadKeepDirStructure ?? true
|
form.isDownloadFileKeepDirStructure = config.settings.isDownloadKeepDirStructure ?? false
|
||||||
|
form.isDownloadFolderKeepDirStructure = config.settings.isDownloadFolderKeepDirStructure ?? true
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleDownloadDirClick () {
|
async function handleDownloadDirClick () {
|
||||||
@@ -611,9 +637,15 @@ function handelIsUploadKeepDirStructureChange (val:ICheckBoxValueType) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function handelIsDownloadKeepDirStructureChange (val:ICheckBoxValueType) {
|
function handelIsDownloadFileKeepDirStructureChange (val:ICheckBoxValueType) {
|
||||||
saveConfig({
|
saveConfig({
|
||||||
'settings.isDownloadKeepDirStructure': val
|
'settings.isDownloadFileKeepDirStructure': val
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function handelIsDownloadFolderKeepDirStructureChange (val:ICheckBoxValueType) {
|
||||||
|
saveConfig({
|
||||||
|
'settings.isDownloadFolderKeepDirStructure': val
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,3 +45,34 @@ export const useFileTransferStore = defineStore('fileTransfer', {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const useDownloadFileTransferStore = defineStore('downloadFileTransfer', {
|
||||||
|
state: () => {
|
||||||
|
return {
|
||||||
|
downloadFileTransferList: [] as IStringKeyMap[],
|
||||||
|
success: false,
|
||||||
|
finished: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
refreshDownloadFileTransferList (newData: IStringKeyMap) {
|
||||||
|
this.downloadFileTransferList = newData.fullList ?? []
|
||||||
|
this.success = newData.success
|
||||||
|
this.finished = newData.finished
|
||||||
|
},
|
||||||
|
resetDownloadFileTransferList () {
|
||||||
|
this.downloadFileTransferList = []
|
||||||
|
this.success = false
|
||||||
|
this.finished = false
|
||||||
|
},
|
||||||
|
getDownloadFileTransferList () {
|
||||||
|
return this.downloadFileTransferList
|
||||||
|
},
|
||||||
|
isFinished () {
|
||||||
|
return this.finished
|
||||||
|
},
|
||||||
|
isSuccess () {
|
||||||
|
return this.success
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
export const cancelDownloadLoadingFileList = 'cancelDownloadLoadingFileList'
|
||||||
|
export const refreshDownloadFileTransferList = 'refreshDownloadFileTransferList'
|
||||||
Vendored
+6
@@ -57,6 +57,12 @@ interface ManageApiType {
|
|||||||
* unset manage config to ctx && will not save to configPath
|
* unset manage config to ctx && will not save to configPath
|
||||||
*/
|
*/
|
||||||
unsetConfig: (key: string, propName: string) => void
|
unsetConfig: (key: string, propName: string) => void
|
||||||
|
/**
|
||||||
|
* get bucket list
|
||||||
|
*/
|
||||||
|
getBucketListRecursively: (
|
||||||
|
param?: IStringKeyMap
|
||||||
|
) => Promise<any | ManageError>;
|
||||||
/**
|
/**
|
||||||
* get bucket list
|
* get bucket list
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user