Skip to content

Commit 473d750

Browse files
committed
Fixed: File upload
1 parent ad16cfc commit 473d750

File tree

5 files changed

+111
-73
lines changed

5 files changed

+111
-73
lines changed

ui/.env.development

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ VITE_PUBLIC_PATH=/koko
88
VITE_KOKO_WS_URL="ws://localhost:5050"
99

1010
# API 接口路径
11-
VITE_KOKO_API_URL="http://localhost:5050"
11+
VITE_KOKO_API_URL="http://localhost:8080"
1212

1313
# 静态资路径
14-
VITE_KOKO_STATIC_URL="http://localhost:5050"
14+
VITE_KOKO_STATIC_URL="http://localhost:8080"
1515

1616
# 打包压缩后是否删除源文件
1717
VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE=false

ui/src/components/FileManagement/components/fileManage/index.vue

+7-9
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,10 @@
5353

5454
<n-upload
5555
abstract
56-
multiple
56+
:multiple="false"
5757
:show-retry-button="false"
5858
:custom-request="customRequest"
59-
v-model:file-list="fileList"
59+
v-model:file-list="uploadFileList"
6060
@change="handleUploadFileChange"
6161
>
6262
<n-button-group>
@@ -88,7 +88,7 @@
8888
v-model:show="showInner"
8989
>
9090
<n-drawer-content :title="t('TransferHistory')">
91-
<n-scrollbar style="max-height: 400px" v-if="fileList.length > 0">
91+
<n-scrollbar style="max-height: 400px" v-if="uploadFileList">
9292
<n-upload-file-list />
9393
</n-scrollbar>
9494

@@ -192,7 +192,7 @@ export interface IFilePath {
192192
showArrow: boolean;
193193
}
194194
195-
const props = withDefaults(
195+
withDefaults(
196196
defineProps<{
197197
columns: DataTableColumns<RowData>;
198198
}>(),
@@ -201,8 +201,6 @@ const props = withDefaults(
201201
}
202202
);
203203
204-
// todo)) 小屏幕下的宽度适配
205-
206204
const { t } = useI18n();
207205
const message = useMessage();
208206
const options = getDropSelections(t);
@@ -227,7 +225,7 @@ const scrollRef = ref(null);
227225
228226
const currentRowData = ref<RowData>();
229227
const filePathList = ref<IFilePath[]>([]);
230-
const fileList = ref<UploadFileInfo[]>([]);
228+
const uploadFileList = ref<UploadFileInfo[]>([]);
231229
232230
watch(
233231
() => fileManageStore.currentPath,
@@ -500,7 +498,7 @@ const handleUploadFileChange = (options: { fileList: Array<UploadFileInfo> }) =>
500498
showInner.value = true;
501499
502500
if (options.fileList.length > 0) {
503-
fileList.value = options.fileList;
501+
uploadFileList.value = options.fileList;
504502
}
505503
};
506504
@@ -511,7 +509,7 @@ const handleUploadFileChange = (options: { fileList: Array<UploadFileInfo> }) =>
511509
* @param onProgress
512510
*/
513511
const customRequest = ({ onFinish, onError, onProgress }: UploadCustomRequestOptions) => {
514-
mittBus.emit('file-upload', { fileList, onFinish, onError, onProgress });
512+
mittBus.emit('file-upload', { uploadFileList, onFinish, onError, onProgress });
515513
};
516514
517515
const handleOpenTransferList = () => {

ui/src/hooks/useFileManage.ts

+100-60
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { computed } from 'vue';
21
import { useRoute } from 'vue-router';
2+
import { computed, ref, watch } from 'vue';
33
import { useWebSocket } from '@vueuse/core';
44
import { createDiscreteApi, darkTheme } from 'naive-ui';
55
import { useFileManageStore } from '@/store/modules/fileManage.ts';
@@ -14,6 +14,8 @@ import type { RouteRecordNameGeneric } from 'vue-router';
1414
import type { ConfigProviderProps, UploadFileInfo } from 'naive-ui'
1515
import type { MessageApiInjection } from 'naive-ui/es/message/src/MessageProvider';
1616
import type { IFileManage, IFileManageConnectData, IFileManageSftpFileItem } from '@/hooks/interface';
17+
import { message } from '@/languages/modules';
18+
import { PercentFilled } from '@vicons/material';
1719

1820
export enum MessageType {
1921
CONNECT = 'CONNECT',
@@ -227,23 +229,14 @@ const initSocketEvent = (socket: WebSocket, t: any) => {
227229
mittBus.emit('reload-table');
228230
}
229231

230-
if (message.cmd === 'upload' && message.data !== 'ok') {
232+
if (message.cmd === 'upload' && message.data === 'ok') {
231233
fileManageStore.setReceived(true);
232234

233-
socket.send(
234-
JSON.stringify({
235-
cmd: 'upload',
236-
type: 'SFTP_DATA',
237-
id: message.id,
238-
raw: '',
239-
data: JSON.stringify({
240-
offSet: 0,
241-
merge: true,
242-
size: 0,
243-
path: message.data
244-
})
245-
})
246-
);
235+
globalTipsMessage.success(t('UploadSuccess'));
236+
}
237+
238+
if (message.cmd === 'upload' && message.data !== 'ok') {
239+
fileManageStore.setReceived(true);
247240
}
248241

249242
if (message.cmd === 'download' && message.data) {
@@ -272,7 +265,16 @@ const initSocketEvent = (socket: WebSocket, t: any) => {
272265
}
273266

274267
case MessageType.SFTP_BINARY: {
275-
receivedBuffers.push(message.raw);
268+
const binaryString = atob(message.raw);
269+
const len = binaryString.length;
270+
const bytes = new Uint8Array(len);
271+
272+
273+
for (let i = 0; i < len; i++) {
274+
bytes[i] = binaryString.charCodeAt(i);
275+
}
276+
277+
receivedBuffers.push(bytes);
276278

277279
break;
278280
}
@@ -425,7 +427,7 @@ const generateUploadChunks = async (
425427
socket: WebSocket,
426428
fileInfo: UploadFileInfo,
427429
CHUNK_SIZE: number,
428-
sentChunks: number
430+
sentChunks: Ref<number>
429431
) => {
430432
const fileManageStore = useFileManageStore();
431433

@@ -448,13 +450,13 @@ const generateUploadChunks = async (
448450
const arrayBuffer: ArrayBuffer = await sliceChunk.arrayBuffer();
449451
const base64String: string = arrayBufferToBase64(arrayBuffer);
450452

451-
sendData.offSet = sentChunks * CHUNK_SIZE;
453+
sendData.offSet = sentChunks.value * CHUNK_SIZE;
452454
sendBody.raw = base64String;
453455
sendBody.data = JSON.stringify(sendData);
454456

455457
socket.send(JSON.stringify(sendBody));
456458

457-
sentChunks++;
459+
sentChunks.value++
458460

459461
return new Promise<boolean>(resolve => {
460462
const interval = setInterval(() => {
@@ -469,55 +471,93 @@ const generateUploadChunks = async (
469471
/**
470472
* @description 上传文件
471473
*/
472-
const handleFileUpload = (
474+
const handleFileUpload = async (
473475
socket: WebSocket,
474-
fileList: Ref<Array<UploadFileInfo>>,
475-
onProgress: any,
476+
uploadFileList: Ref<Array<UploadFileInfo>>,
477+
_onProgress: any,
476478
onFinish: () => void,
477-
onError: () => void
479+
onError: () => void,
480+
t: any
478481
) => {
482+
const maxSliceCount = 100;
483+
const maxChunkSize = 1024 * 1024 * 10;
479484
const fileManageStore = useFileManageStore();
480-
let CHUNK_SIZE = 1024 * 1024 * 3;
481-
482-
fileList.value.forEach(async (fileInfo: UploadFileInfo) => {
483-
if (fileInfo.file) {
484-
let sliceCount = Math.ceil(fileInfo.file?.size / CHUNK_SIZE);
485-
let sliceChunks = [];
486-
487-
for (let i = 0; i < sliceCount; i++) {
488-
sliceChunks.push(fileInfo.file.slice(i * CHUNK_SIZE, (i + 1) * CHUNK_SIZE));
485+
const loadingMessage = globalTipsMessage.loading('上传进度: 0%', { duration: 1000000000 });
486+
const fileInfo = uploadFileList.value[0];
487+
488+
let sliceChunks = [];
489+
let CHUNK_SIZE = 1024 * 1024 * 5;
490+
let sentChunks = ref(0);
491+
492+
const unwatch = watch(
493+
() => sentChunks.value,
494+
(newValue) => {
495+
const percent = (newValue / sliceChunks.length) * 100;
496+
497+
console.log(
498+
'%c DEBUG[ percent ]:',
499+
'font-size:13px; background: #1ab394; color:#fff;',
500+
percent
501+
);
502+
503+
loadingMessage.content = `上传进度: ${Math.floor(percent)}%`;
504+
505+
if (percent >= 100) {
506+
onFinish();
507+
loadingMessage.destroy();
508+
mittBus.emit('reload-table');
509+
unwatch();
489510
}
511+
}
512+
);
490513

491-
let sentChunks = 0;
492-
493-
try {
494-
for (const sliceChunk of sliceChunks) {
495-
fileManageStore.setReceived(false);
496-
await generateUploadChunks(sliceChunk, socket, fileInfo, CHUNK_SIZE, sentChunks);
497-
498-
sentChunks++;
499-
500-
const percent = (sentChunks / sliceChunks.length) * 100;
514+
if (fileInfo && fileInfo.file) {
515+
let sliceCount = Math.ceil(fileInfo.file?.size / CHUNK_SIZE);
516+
517+
// 如果切片数量大于最大切片数量,那么调大切片大小
518+
if (sliceCount > maxSliceCount) {
519+
sliceCount = maxSliceCount;
520+
CHUNK_SIZE = Math.ceil(fileInfo.file?.size / maxSliceCount);
521+
}
501522

502-
console.log(
503-
'%c DEBUG[ percent ]:',
504-
'font-size:13px; background: #1ab394; color:#fff;',
505-
percent
506-
);
523+
// 如果切片大小大于最大切片大小,那么依然调整切片数量
524+
if (CHUNK_SIZE > maxChunkSize) {
525+
CHUNK_SIZE = maxChunkSize;
526+
sliceCount = Math.ceil(fileInfo.file?.size / CHUNK_SIZE);
527+
}
507528

508-
onProgress({ percent });
529+
for (let i = 0; i < sliceCount; i++) {
530+
sliceChunks.push(fileInfo.file.slice(i * CHUNK_SIZE, (i + 1) * CHUNK_SIZE));
531+
}
509532

510-
if (percent === 100) {
511-
onFinish();
533+
try {
534+
for (const sliceChunk of sliceChunks) {
535+
fileManageStore.setReceived(false);
512536

513-
mittBus.emit('reload-table');
514-
}
515-
}
516-
} catch (e) {
517-
onError();
537+
await generateUploadChunks(sliceChunk, socket, fileInfo, CHUNK_SIZE, sentChunks);
518538
}
539+
540+
// 结束 chunk 发送 merge: true
541+
socket.send(
542+
JSON.stringify({
543+
cmd: 'upload',
544+
type: 'SFTP_DATA',
545+
id: fileManageStore.messageId,
546+
raw: '',
547+
data: JSON.stringify({
548+
offSet: 0,
549+
merge: true,
550+
size: 0,
551+
path: `${fileManageStore.currentPath}/${fileInfo.name}`
552+
})
553+
})
554+
);
555+
556+
} catch (e) {
557+
loadingMessage.destroy();
558+
onError();
519559
}
520-
});
560+
}
521561
};
522562

523563
/**
@@ -532,17 +572,17 @@ export const useFileManage = (token: string, t: any) => {
532572
mittBus.on(
533573
'file-upload',
534574
({
535-
fileList,
575+
uploadFileList,
536576
onFinish,
537577
onError,
538578
onProgress
539579
}: {
540-
fileList: Ref<Array<UploadFileInfo>>;
580+
uploadFileList: Ref<Array<UploadFileInfo>>;
541581
onFinish: () => void;
542582
onError: () => void;
543583
onProgress: (e: { percent: number }) => void;
544584
}) => {
545-
handleFileUpload(<WebSocket>socket, fileList, onProgress, onFinish, onError);
585+
handleFileUpload(<WebSocket>socket, uploadFileList, onProgress, onFinish, onError, t);
546586
}
547587
);
548588

ui/src/store/modules/fileManage.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export const useFileManageStore = defineStore('fileManage', {
2727
if (fileList) {
2828
console.log(
2929
'%c DEBUG[ fileList ]-72:',
30-
'font-size:13px; background:#DCDCDC; color:#2F4F4F;',
30+
'font-size:13px; background: #1ab394; color:#fff;',
3131
fileList
3232
);
3333
this.fileList = fileList;

ui/src/utils/mittBus.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ type Event = {
2020
'set-theme': { themeName: string };
2121
'file-manage': { path: string; type: ManageTypes; new_name?: string };
2222
'file-upload': {
23-
fileList: Ref<Array<UploadFileInfo>>;
23+
uploadFileList: Ref<Array<UploadFileInfo>>;
2424
onFinish: () => void;
2525
onError: () => void;
2626
onProgress: (e: { percent: number }) => void;

0 commit comments

Comments
 (0)