✨ 修改下载文件逻辑.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import type { DataGrid, Pagination } from '@/types/global';
|
||||
import type { TableData } from '@arco-design/web-vue/es/table/interface';
|
||||
import { httpBaseUrl } from '@/utils/env';
|
||||
import axios from 'axios';
|
||||
import qs from 'query-string';
|
||||
|
||||
@@ -46,17 +47,25 @@ export interface HostSftpLogExtra {
|
||||
* 分页查询 SFTP 操作日志
|
||||
*/
|
||||
export function getHostSftpLogPage(request: HostSftpLogQueryRequest) {
|
||||
return axios.post<DataGrid<HostSftpLogQueryResponse>>('/asset/host-sftp-log/query', request);
|
||||
return axios.post<DataGrid<HostSftpLogQueryResponse>>('/asset/host-sftp/query-log', request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除 SFTP 操作日志
|
||||
*/
|
||||
export function deleteHostSftpLog(idList: Array<number>) {
|
||||
return axios.delete('/asset/host-sftp-log/delete', {
|
||||
return axios.delete('/asset/host-sftp/delete-log', {
|
||||
params: { idList },
|
||||
paramsSerializer: params => {
|
||||
return qs.stringify(params, { arrayFormat: 'comma' });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载文件
|
||||
*/
|
||||
export function downloadWithTransferToken(channelId: string, transferToken: string) {
|
||||
window.open(`${httpBaseUrl}/asset/host-sftp/download?channelId=${channelId}&transferToken=${transferToken}`, 'newWindow');
|
||||
}
|
||||
|
||||
@@ -172,9 +172,9 @@
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { HostSftpLogQueryRequest, HostSftpLogQueryResponse } from '@/api/asset/host-sftp-log';
|
||||
import type { HostSftpLogQueryRequest, HostSftpLogQueryResponse } from '@/api/asset/host-sftp';
|
||||
import { reactive, ref, onMounted } from 'vue';
|
||||
import { getHostSftpLogPage, deleteHostSftpLog } from '@/api/asset/host-sftp-log';
|
||||
import { getHostSftpLogPage, deleteHostSftpLog } from '@/api/asset/host-sftp';
|
||||
import { sftpOperatorTypeKey, sftpOperatorResultKey, SftpOperatorType } from '../types/const';
|
||||
import { usePagination, useRowSelection } from '@/types/table';
|
||||
import { useDictStore } from '@/store';
|
||||
|
||||
@@ -8,58 +8,53 @@ export default class SftpTransferDownloader implements ISftpTransferDownloader {
|
||||
|
||||
public abort: boolean;
|
||||
|
||||
private blobArr: Array<Blob>;
|
||||
private client: WebSocket;
|
||||
private item: SftpTransferItem;
|
||||
|
||||
constructor(item: SftpTransferItem, client: WebSocket) {
|
||||
this.abort = false;
|
||||
this.blobArr = [];
|
||||
this.item = item;
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
// 开始下载
|
||||
startDownload() {
|
||||
initDownload() {
|
||||
this.item.status = TransferStatus.TRANSFERRING;
|
||||
// 发送开始下载信息
|
||||
this.client?.send(JSON.stringify({
|
||||
type: TransferOperatorType.DOWNLOAD_START,
|
||||
type: TransferOperatorType.DOWNLOAD_INIT,
|
||||
path: getPath(this.item.parentPath + '/' + this.item.name),
|
||||
hostId: this.item.hostId
|
||||
}));
|
||||
}
|
||||
|
||||
// 接收 blob
|
||||
resolveBlob(blob: Blob) {
|
||||
this.blobArr.push(blob);
|
||||
this.item.currentSize += blob.size;
|
||||
}
|
||||
|
||||
// 下载完成
|
||||
downloadFinish() {
|
||||
if (this.abort) {
|
||||
// 中断则不触发下载
|
||||
this.blobArr = [];
|
||||
return;
|
||||
}
|
||||
try {
|
||||
// 触发下载
|
||||
saveAs(new Blob(this.blobArr, {
|
||||
type: 'application/octet-stream'
|
||||
}), getFileName(this.item.name));
|
||||
// 设置实际大小
|
||||
this.item.currentSize = this.item.totalSize;
|
||||
if (this.item.totalSize === 0) {
|
||||
// 空文件直接触发下载
|
||||
try {
|
||||
// 触发下载
|
||||
saveAs(new Blob([], {
|
||||
type: 'application/octet-stream'
|
||||
}), getFileName(this.item.name));
|
||||
this.item.status = TransferStatus.SUCCESS;
|
||||
} catch (e) {
|
||||
this.item.status = TransferStatus.ERROR;
|
||||
this.item.errorMessage = '保存失败';
|
||||
}
|
||||
} else {
|
||||
this.item.status = TransferStatus.SUCCESS;
|
||||
} catch (e) {
|
||||
this.item.status = TransferStatus.ERROR;
|
||||
this.item.errorMessage = '保存失败';
|
||||
} finally {
|
||||
this.blobArr = [];
|
||||
}
|
||||
}
|
||||
|
||||
// 下载失败
|
||||
downloadError(msg: string | undefined) {
|
||||
this.blobArr = [];
|
||||
this.item.status = TransferStatus.ERROR;
|
||||
this.item.errorMessage = msg || '下载失败';
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import { TransferReceiverType, TransferStatus, TransferType } from '../types/ter
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
import { getTerminalAccessToken, openHostTransferChannel } from '@/api/asset/host-terminal';
|
||||
import { nextId } from '@/utils';
|
||||
import { downloadWithTransferToken } from '@/api/asset/host-sftp';
|
||||
import SftpTransferUploader from './sftp-transfer-uploader';
|
||||
import SftpTransferDownloader from './sftp-transfer-downloader';
|
||||
|
||||
@@ -144,7 +145,9 @@ export default class SftpTransferManager implements ISftpTransferManager {
|
||||
// 计算传输进度
|
||||
private calcProgress() {
|
||||
this.transferList.forEach(item => {
|
||||
item.progress = (item.currentSize / item.totalSize * 100).toFixed(2);
|
||||
if (item.totalSize != 0) {
|
||||
item.progress = (item.currentSize / item.totalSize * 100).toFixed(2);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -165,7 +168,7 @@ export default class SftpTransferManager implements ISftpTransferManager {
|
||||
this.uploadFile();
|
||||
} else {
|
||||
// 下载
|
||||
this.uploadDownload();
|
||||
this.downloadFile();
|
||||
}
|
||||
} else {
|
||||
// 无任务关闭会话
|
||||
@@ -175,27 +178,28 @@ export default class SftpTransferManager implements ISftpTransferManager {
|
||||
|
||||
// 接收消息
|
||||
private async resolveMessage(message: MessageEvent) {
|
||||
if (message.data instanceof Blob) {
|
||||
// 二进制消息 下载数据
|
||||
this.resolveDownloadBlob(message.data);
|
||||
} else {
|
||||
// 文本消息
|
||||
const data = JSON.parse(message.data) as TransferOperatorResponse;
|
||||
if (data.type === TransferReceiverType.NEXT_TRANSFER
|
||||
|| data.type === TransferReceiverType.UPLOAD_FINISH
|
||||
|| data.type === TransferReceiverType.UPLOAD_ERROR) {
|
||||
// 执行下一个传输任务
|
||||
this.resolveNextTransfer(data);
|
||||
} else if (data.type === TransferReceiverType.UPLOAD_NEXT_BLOCK) {
|
||||
// 接收下一块上传数据
|
||||
await this.resolveUploadNextBlock();
|
||||
} else if (data.type === TransferReceiverType.DOWNLOAD_FINISH) {
|
||||
// 下载完成
|
||||
this.resolveDownloadFinish();
|
||||
} else if (data.type === TransferReceiverType.DOWNLOAD_ERROR) {
|
||||
// 下载失败
|
||||
this.resolveDownloadError(data.msg);
|
||||
}
|
||||
// 文本消息
|
||||
const data = JSON.parse(message.data) as TransferOperatorResponse;
|
||||
if (data.type === TransferReceiverType.NEXT_TRANSFER
|
||||
|| data.type === TransferReceiverType.UPLOAD_FINISH
|
||||
|| data.type === TransferReceiverType.UPLOAD_ERROR) {
|
||||
// 执行下一个传输任务
|
||||
this.resolveNextTransfer(data);
|
||||
} else if (data.type === TransferReceiverType.UPLOAD_NEXT_BLOCK) {
|
||||
// 接收下一块上传数据
|
||||
await this.resolveUploadNextBlock();
|
||||
} else if (data.type === TransferReceiverType.DOWNLOAD_START) {
|
||||
// 开始下载
|
||||
this.resolveDownloadStart(data);
|
||||
} else if (data.type === TransferReceiverType.DOWNLOAD_PROGRESS) {
|
||||
// 下载进度
|
||||
this.resolveDownloadProgress(data);
|
||||
} else if (data.type === TransferReceiverType.DOWNLOAD_FINISH) {
|
||||
// 下载完成
|
||||
this.resolveDownloadFinish();
|
||||
} else if (data.type === TransferReceiverType.DOWNLOAD_ERROR) {
|
||||
// 下载失败
|
||||
this.resolveDownloadError(data.msg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,11 +212,11 @@ export default class SftpTransferManager implements ISftpTransferManager {
|
||||
}
|
||||
|
||||
// 下载文件
|
||||
private uploadDownload() {
|
||||
private downloadFile() {
|
||||
// 创建下载器
|
||||
this.currentDownloader = new SftpTransferDownloader(this.currentItem as SftpTransferItem, this.client as WebSocket);
|
||||
// 开始下载
|
||||
this.currentDownloader.startDownload();
|
||||
// 初始化下载
|
||||
this.currentDownloader.initDownload();
|
||||
}
|
||||
|
||||
// 接收下一个传输任务响应
|
||||
@@ -251,9 +255,16 @@ export default class SftpTransferManager implements ISftpTransferManager {
|
||||
}
|
||||
}
|
||||
|
||||
// 接收下载数据
|
||||
private resolveDownloadBlob(blob: Blob) {
|
||||
this.currentDownloader?.resolveBlob(blob);
|
||||
// 接收开始下载响应
|
||||
private resolveDownloadStart(data: TransferOperatorResponse) {
|
||||
downloadWithTransferToken(data.channelId as string, data.transferToken as string);
|
||||
}
|
||||
|
||||
// 接收下载进度响应
|
||||
private resolveDownloadProgress(data: TransferOperatorResponse) {
|
||||
if (this.currentItem && data.currentSize) {
|
||||
this.currentItem.currentSize = data.currentSize;
|
||||
}
|
||||
}
|
||||
|
||||
// 接收下载完成响应
|
||||
|
||||
@@ -336,7 +336,7 @@ export const TransferOperatorType = {
|
||||
UPLOAD_START: 'uploadStart',
|
||||
UPLOAD_FINISH: 'uploadFinish',
|
||||
UPLOAD_ERROR: 'uploadError',
|
||||
DOWNLOAD_START: 'downloadStart',
|
||||
DOWNLOAD_INIT: 'downloadInit',
|
||||
DOWNLOAD_ABORT: 'downloadAbort',
|
||||
};
|
||||
|
||||
@@ -346,6 +346,8 @@ export const TransferReceiverType = {
|
||||
UPLOAD_NEXT_BLOCK: 'uploadNextBlock',
|
||||
UPLOAD_FINISH: 'uploadFinish',
|
||||
UPLOAD_ERROR: 'uploadError',
|
||||
DOWNLOAD_START: 'downloadStart',
|
||||
DOWNLOAD_PROGRESS: 'downloadProgress',
|
||||
DOWNLOAD_FINISH: 'downloadFinish',
|
||||
DOWNLOAD_ERROR: 'downloadError',
|
||||
};
|
||||
|
||||
@@ -432,10 +432,8 @@ export interface ISftpTransferUploader {
|
||||
export interface ISftpTransferDownloader {
|
||||
// 是否中断
|
||||
abort: boolean;
|
||||
// 开始下载
|
||||
startDownload: () => void;
|
||||
// 接收 blob
|
||||
resolveBlob: (blob: Blob) => void;
|
||||
// 初始化下载
|
||||
initDownload: () => void;
|
||||
// 下载完成
|
||||
downloadFinish: () => void;
|
||||
// 下载失败
|
||||
@@ -461,8 +459,11 @@ export interface SftpTransferItem {
|
||||
|
||||
// 传输操作响应
|
||||
export interface TransferOperatorResponse {
|
||||
channelId?: string;
|
||||
type: string;
|
||||
hostId?: number;
|
||||
currentSize?: number;
|
||||
transferToken?: string;
|
||||
success: boolean;
|
||||
msg?: string;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user