mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-10-09 23:17:21 +08:00
fix: 解决拖拽上传文件夹文件上传不全的问题 (#3865)
Refs https://github.com/1Panel-dev/1Panel/issues/3848
This commit is contained in:
parent
6a903b7fdf
commit
3fd7aa17a8
5 changed files with 55 additions and 12 deletions
|
@ -2,6 +2,7 @@ package docker
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"github.com/docker/docker/api/types/container"
|
||||||
|
|
||||||
"github.com/1Panel-dev/1Panel/backend/app/model"
|
"github.com/1Panel-dev/1Panel/backend/app/model"
|
||||||
"github.com/1Panel-dev/1Panel/backend/global"
|
"github.com/1Panel-dev/1Panel/backend/global"
|
||||||
|
@ -45,7 +46,7 @@ func NewDockerClient() (*client.Client, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c Client) ListAllContainers() ([]types.Container, error) {
|
func (c Client) ListAllContainers() ([]types.Container, error) {
|
||||||
var options types.ContainerListOptions
|
var options container.ListOptions
|
||||||
containers, err := c.cli.ContainerList(context.Background(), options)
|
containers, err := c.cli.ContainerList(context.Background(), options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -55,7 +56,7 @@ func (c Client) ListAllContainers() ([]types.Container, error) {
|
||||||
|
|
||||||
func (c Client) ListContainersByName(names []string) ([]types.Container, error) {
|
func (c Client) ListContainersByName(names []string) ([]types.Container, error) {
|
||||||
var (
|
var (
|
||||||
options types.ContainerListOptions
|
options container.ListOptions
|
||||||
res []types.Container
|
res []types.Container
|
||||||
)
|
)
|
||||||
options.All = true
|
options.All = true
|
||||||
|
|
|
@ -1127,6 +1127,7 @@ const message = {
|
||||||
ignoreCertificate: 'Ignore Certificate',
|
ignoreCertificate: 'Ignore Certificate',
|
||||||
ignoreCertificateHelper:
|
ignoreCertificateHelper:
|
||||||
'Ignoring untrusted certificates during downloads may lead to data leakage or tampering. Please use this option with caution, only when trusting the download source.',
|
'Ignoring untrusted certificates during downloads may lead to data leakage or tampering. Please use this option with caution, only when trusting the download source.',
|
||||||
|
uploadOverLimit: 'The number of files exceeds 1000! Please compress and upload',
|
||||||
},
|
},
|
||||||
ssh: {
|
ssh: {
|
||||||
autoStart: 'Auto Start',
|
autoStart: 'Auto Start',
|
||||||
|
|
|
@ -1071,6 +1071,7 @@ const message = {
|
||||||
ignoreCertificate: '忽略不可信證書',
|
ignoreCertificate: '忽略不可信證書',
|
||||||
ignoreCertificateHelper:
|
ignoreCertificateHelper:
|
||||||
'下載時忽略不可信證書可能導致數據洩露或篡改。請謹慎使用此選項,僅在信任下載源的情況下啟用',
|
'下載時忽略不可信證書可能導致數據洩露或篡改。請謹慎使用此選項,僅在信任下載源的情況下啟用',
|
||||||
|
uploadOverLimit: '文件數量超過 1000! 請壓縮後上傳',
|
||||||
},
|
},
|
||||||
ssh: {
|
ssh: {
|
||||||
autoStart: '開機自啟',
|
autoStart: '開機自啟',
|
||||||
|
|
|
@ -1072,6 +1072,7 @@ const message = {
|
||||||
ignoreCertificate: '忽略不可信证书',
|
ignoreCertificate: '忽略不可信证书',
|
||||||
ignoreCertificateHelper:
|
ignoreCertificateHelper:
|
||||||
'下载时忽略不可信证书可能导致数据泄露或篡改。请谨慎使用此选项,仅在信任下载源的情况下启用',
|
'下载时忽略不可信证书可能导致数据泄露或篡改。请谨慎使用此选项,仅在信任下载源的情况下启用',
|
||||||
|
uploadOverLimit: '文件数量超过 1000!请压缩后上传',
|
||||||
},
|
},
|
||||||
ssh: {
|
ssh: {
|
||||||
autoStart: '开机自启',
|
autoStart: '开机自启',
|
||||||
|
|
|
@ -92,7 +92,7 @@ import { UploadFile, UploadFiles, UploadInstance, UploadProps, UploadRawFile } f
|
||||||
import { ChunkUploadFileData, UploadFileData } from '@/api/modules/files';
|
import { ChunkUploadFileData, UploadFileData } from '@/api/modules/files';
|
||||||
import i18n from '@/lang';
|
import i18n from '@/lang';
|
||||||
import DrawerHeader from '@/components/drawer-header/index.vue';
|
import DrawerHeader from '@/components/drawer-header/index.vue';
|
||||||
import { MsgError, MsgSuccess } from '@/utils/message';
|
import { MsgError, MsgSuccess, MsgWarning } from '@/utils/message';
|
||||||
import { Close } from '@element-plus/icons-vue';
|
import { Close } from '@element-plus/icons-vue';
|
||||||
import { TimeoutEnum } from '@/enums/http-enum';
|
import { TimeoutEnum } from '@/enums/http-enum';
|
||||||
|
|
||||||
|
@ -120,6 +120,8 @@ const uploaderFiles = ref<UploadFiles>([]);
|
||||||
const isUploadFolder = ref(false);
|
const isUploadFolder = ref(false);
|
||||||
const hoverIndex = ref(null);
|
const hoverIndex = ref(null);
|
||||||
const uploadType = ref('file');
|
const uploadType = ref('file');
|
||||||
|
const tmpFiles = ref<UploadFiles>([]);
|
||||||
|
const breakFlag = ref(false);
|
||||||
|
|
||||||
const upload = (commnad: string) => {
|
const upload = (commnad: string) => {
|
||||||
uploadType.value = commnad;
|
uploadType.value = commnad;
|
||||||
|
@ -140,7 +142,13 @@ const handleDragover = (event: DragEvent) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDrop = (event: DragEvent) => {
|
const initTempFiles = () => {
|
||||||
|
tmpFiles.value = [];
|
||||||
|
breakFlag.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDrop = async (event: DragEvent) => {
|
||||||
|
initTempFiles();
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
const items = event.dataTransfer.items;
|
const items = event.dataTransfer.items;
|
||||||
|
|
||||||
|
@ -148,9 +156,15 @@ const handleDrop = (event: DragEvent) => {
|
||||||
for (let i = 0; i < items.length; i++) {
|
for (let i = 0; i < items.length; i++) {
|
||||||
const entry = items[i].webkitGetAsEntry();
|
const entry = items[i].webkitGetAsEntry();
|
||||||
if (entry) {
|
if (entry) {
|
||||||
traverseFileTree(entry);
|
await traverseFileTree(entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!breakFlag.value) {
|
||||||
|
uploaderFiles.value = uploaderFiles.value.concat(tmpFiles.value);
|
||||||
|
} else {
|
||||||
|
MsgWarning(i18n.global.t('file.uploadOverLimit'));
|
||||||
|
}
|
||||||
|
initTempFiles();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -176,19 +190,44 @@ const convertFileToUploadFile = (file: File, path: string): UploadFile => {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const traverseFileTree = (item: any, path = '') => {
|
const traverseFileTree = async (item: any, path = '') => {
|
||||||
path = path || '';
|
path = path || '';
|
||||||
|
|
||||||
if (item.isFile) {
|
if (item.isFile) {
|
||||||
item.file((file: File) => {
|
if (tmpFiles.value.length > 1000) {
|
||||||
uploaderFiles.value.push(convertFileToUploadFile(file, path));
|
breakFlag.value = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await new Promise<void>((resolve) => {
|
||||||
|
item.file((file: File) => {
|
||||||
|
if (!breakFlag.value) {
|
||||||
|
tmpFiles.value.push(convertFileToUploadFile(file, path));
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
} else if (item.isDirectory) {
|
} else if (item.isDirectory) {
|
||||||
const dirReader = item.createReader();
|
const dirReader = item.createReader();
|
||||||
dirReader.readEntries((entries) => {
|
const readEntries = async () => {
|
||||||
for (let i = 0; i < entries.length; i++) {
|
const entries = await new Promise<any[]>((resolve) => {
|
||||||
traverseFileTree(entries[i], path + item.name + '/');
|
dirReader.readEntries((entries) => {
|
||||||
|
resolve(entries);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
if (entries.length === 0) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
for (let i = 0; i < entries.length; i++) {
|
||||||
|
await traverseFileTree(entries[i], path + item.name + '/');
|
||||||
|
if (breakFlag.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await readEntries();
|
||||||
|
};
|
||||||
|
await readEntries();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue