🔨 文件上传.

This commit is contained in:
lijiahang
2024-02-21 16:32:29 +08:00
parent 63455d7654
commit f4d63d4b99
10 changed files with 180 additions and 30 deletions

View File

@@ -31,11 +31,8 @@ public class SftpFileVO {
@Schema(description = "文件后缀")
private String suffix;
@Schema(description = "文件大小")
private String size;
@Schema(description = "文件大小(byte)")
private Long sizeByte;
private Long size;
@Schema(description = "属性")
private String attr;

View File

@@ -157,8 +157,7 @@ public class SftpSession extends TerminalSession implements ISftpSession {
file.setName(sftpFile.getName());
file.setPath(sftpFile.getPath());
file.setSuffix(Files1.getSuffix(sftpFile.getName()));
file.setSize(Files1.getSize(sftpFile.getSize()));
file.setSizeByte(sftpFile.getSize());
file.setSize(sftpFile.getSize());
file.setPermission(sftpFile.getPermission());
file.setUid(sftpFile.getUid());
file.setGid(sftpFile.getGid());

View File

@@ -135,4 +135,24 @@ export function permission10toString(permission: number) {
return res;
}
// 获取文件大小
export function getFileSize(size: number, scale: number = 2) {
let result;
let unit;
if (size >= 1024 * 1024 * 1024) {
result = (size / (1024 * 1024 * 1024)).toFixed(scale);
unit = 'GB';
} else if (size >= 1024 * 1024) {
result = (size / (1024 * 1024)).toFixed(scale);
unit = 'MB';
} else if (size >= 1024) {
result = (size / 1024).toFixed(scale);
unit = 'KB';
} else {
result = size;
unit = 'B';
}
return `${result} ${unit}`;
}
export default null;

View File

@@ -68,7 +68,7 @@
</span>
</a-tooltip>
<!-- 编辑内容 -->
<a-tooltip v-if="canEditable(record.sizeByte, record.attr)"
<a-tooltip v-if="canEditable(record.size, record.attr)"
position="top"
:mini="true"
:overlay-inverse="true"
@@ -204,12 +204,12 @@
};
// 是否可编辑
const canEditable = (sizeByte: number, attr: string) => {
const canEditable = (size: number, attr: string) => {
const typeValue = formatFileType(attr).value;
// 非文件夹和链接文件 并且文件小于 配置大小(MB) 可以编辑
return FILE_TYPE.DIRECTORY.value !== typeValue
&& FILE_TYPE.LINK_FILE.value !== typeValue
&& sizeByte <= previewSize * 1024 * 1024;
&& size <= previewSize * 1024 * 1024;
};
// 点击文件名称

View File

@@ -76,11 +76,11 @@
</script>
<script lang="ts" setup>
import type { SftpUploadItem } from '../../types/terminal.type';
import useVisible from '@/hooks/visible';
import { ref } from 'vue';
import { useTerminalStore } from '@/store';
import { Message } from '@arco-design/web-vue';
import useVisible from '@/hooks/visible';
import { TransferStatus, TransferType } from '../../types/terminal.const';
const { visible, setVisible } = useVisible();
const { transferManager } = useTerminalStore();
@@ -106,10 +106,15 @@
// 添加到上传列表
const files = fileList.value.map(s => {
return {
type: TransferType.UPLOAD,
hostId: hostId.value,
targetPath: parentPath.value + '/' + (s.file.webkitRelativePath || s.file.name),
file: s.file as File
} as SftpUploadItem;
name: s.file.webkitRelativePath || s.file.name,
currentSize: 0,
totalSize: s.file.size,
status: TransferStatus.WAITING,
parentPath: parentPath.value,
file: s.file
};
});
transferManager.addUpload(files);
Message.success('已开始上传, 点击右侧传输列表查看进度');

View File

@@ -1,4 +1,5 @@
import type { TableColumnData } from '@arco-design/web-vue/es/table/interface';
import { getFileSize } from '@/utils/file';
// 表格列
const columns = [
@@ -17,12 +18,15 @@ const columns = [
}
}, {
title: '大小',
dataIndex: 'sizeByte',
dataIndex: 'size',
slotName: 'size',
ellipsis: true,
sortable: {
sortDirections: ['ascend', 'descend'],
},
render: ({ record }) => {
return getFileSize(record.size);
},
}, {
title: '属性',
dataIndex: 'attr',

View File

@@ -6,7 +6,71 @@
:unmount-on-close="false"
:footer="false">
<a-spin class="full" :loading="loading">
{{ transferManager.transferList }}
<a-list class="hosts-list-container"
size="smail"
max-height="100%"
:hoverable="true"
:bordered="false"
:data="transferManager.transferList">
<!-- 空数据 -->
<template #empty>
<a-empty description="无数据" />
</template>
<!-- 数据 -->
<template #item="{ item }">
<a-list-item class="transfer-item-wrapper">
<div class="transfer-item">
<!-- 左侧图标 -->
<div class="transfer-item-left">
<span class="file-icon">
<icon-upload />
</span>
</div>
<!-- 中间信息 -->
<div class="transfer-item-center">
<!-- 文件名称 -->
<a-tooltip position="top"
:mini="true"
:auto-fix-position="false"
content-class="terminal-tooltip-content"
arrow-class="terminal-tooltip-content"
:content="item.name">
<span class="file-name">
{{ item.name }}
</span>
</a-tooltip>
<!-- 传输进度 -->
<span class="transfer-progress">
{{ getFileSize(item.currentSize) }}/{{ getFileSize(item.totalSize) }}
</span>
<!-- 目标目录 -->
<a-tooltip v-if="item.parentPath"
position="top"
:mini="true"
:auto-fix-position="false"
content-class="terminal-tooltip-content"
arrow-class="terminal-tooltip-content"
:content="item.parentPath">
<span class="target-path">
{{ item.parentPath }}
</span>
</a-tooltip>
</div>
<!-- 右侧状态/操作-->
<div class="transfer-item-right">
<!-- 等待传输 -->
<icon-loading v-if="item.status === TransferStatus.WAITING" />
<!-- 传输进度 -->
<a-progress v-else
type="circle"
size="mini"
:status="item.status"
:percent="item.currentSize / item.totalSize" />
</div>
</div>
</a-list-item>
</template>
</a-list>
</a-spin>
</a-drawer>
</template>
@@ -21,6 +85,8 @@
import useLoading from '@/hooks/loading';
import useVisible from '@/hooks/visible';
import { useTerminalStore } from '@/store';
import { getFileSize } from '@/utils/file';
import { TransferStatus } from '../../types/terminal.const';
const { transferManager } = useTerminalStore();
const { visible, setVisible } = useVisible();
@@ -46,12 +112,53 @@
</script>
<style lang="less" scoped>
.form-container {
padding: 12px;
}
@item-left-width: 42px;
@item-right-width: 42px;
@item-center-width: 388px - @item-left-width - @item-right-width;
.command-editor {
height: calc(100vh - 330px);
.transfer-item {
min-height: 36px;
padding: 8px 0;
display: flex;
align-items: center;
&-left {
width: @item-left-width;
display: flex;
justify-content: center;
.file-icon {
color: rgb(var(--arcoblue-6));
font-size: 18px;
}
}
&-center {
width: @item-center-width;
display: flex;
flex-direction: column;
.file-name {
color: var(--color-content-text-1);
overflow: hidden;
text-overflow: ellipsis;
width: fit-content;
max-width: 100%;
}
.transfer-progress, .target-path {
padding-top: 4px;
font-size: 13px;
color: var(--color-neutral-8);
width: fit-content;
}
}
&-right {
width: @item-right-width;
display: flex;
justify-content: center;
}
}
</style>

View File

@@ -1,16 +1,16 @@
import type { ISftpTransferManager, SftpUploadItem } from '../types/terminal.type';
import type { ISftpTransferManager, SftpTransferItem } from '../types/terminal.type';
// sftp 传输管理器实现
export default class SftpTransferManager implements ISftpTransferManager {
transferList: Array<SftpUploadItem>;
transferList: Array<SftpTransferItem>;
constructor() {
this.transferList = [];
}
// 添加上传文件
addUpload(items: Array<SftpUploadItem>): void {
addUpload(items: Array<SftpTransferItem>): void {
this.transferList.push(...items);
}

View File

@@ -285,6 +285,20 @@ export const TerminalShortcutItems: Array<ShortcutKeyItem> = [
},
];
// 传输状态
export const TransferStatus = {
WAITING: 'waiting',
TRANSFERRING: 'normal',
SUCCESS: 'success',
ERROR: 'danger',
};
// 传输类型
export const TransferType = {
UPLOAD: 'upload',
DOWNLOAD: 'download'
};
// 打开 sshSettingModal key
export const openSshSettingModalKey = Symbol();

View File

@@ -358,8 +358,7 @@ export interface SftpFile {
name: string;
path: string;
suffix: string;
size: string;
sizeByte: number;
size: number;
attr: string;
isDir: boolean;
permission: number;
@@ -370,14 +369,19 @@ export interface SftpFile {
// sftp 传输管理器定义
export interface ISftpTransferManager {
transferList: Array<SftpUploadItem>;
transferList: Array<SftpTransferItem>;
// 添加上传文件
addUpload: (items: Array<SftpUploadItem>) => void;
addUpload: (items: Array<SftpTransferItem>) => void;
}
// sftp 上传文件项
export interface SftpUploadItem {
export interface SftpTransferItem {
type: string;
hostId: number;
targetPath: string;
name: string;
parentPath: string;
currentSize: number,
totalSize: number;
status: string;
file: File;
}