@@ -6,6 +6,41 @@ interface FileUploadProps {
6
6
onFilesUploaded : ( files : FileInfo [ ] ) => void ;
7
7
}
8
8
9
+ const getFilesFromDirectory = async ( directory : FileSystemDirectoryEntry ) : Promise < File [ ] > => {
10
+ return new Promise ( ( resolve ) => {
11
+ const files : File [ ] = [ ] ;
12
+ const reader = directory . createReader ( ) ;
13
+
14
+ const readEntries = ( ) => {
15
+ reader . readEntries ( async ( entries ) => {
16
+ if ( ! entries . length ) {
17
+ resolve ( files ) ;
18
+ } else {
19
+ await Promise . all ( entries . map ( async ( entry ) => {
20
+ if ( entry . isFile ) {
21
+ await new Promise ( ( fileResolve ) => {
22
+ ( entry as FileSystemFileEntry ) . file ( ( file ) => {
23
+ const mappedFile = new File ( [ file ] , entry . fullPath , {
24
+ type : file . type ,
25
+ lastModified : file . lastModified
26
+ } ) ;
27
+ files . push ( mappedFile ) ;
28
+ fileResolve ( null ) ;
29
+ } ) ;
30
+ } ) ;
31
+ } else if ( entry . isDirectory ) {
32
+ const subFiles = await getFilesFromDirectory ( entry as FileSystemDirectoryEntry ) ;
33
+ files . push ( ...subFiles ) ;
34
+ }
35
+ } ) ) ;
36
+ readEntries ( ) ;
37
+ }
38
+ } ) ;
39
+ } ;
40
+ readEntries ( ) ;
41
+ } ) ;
42
+ } ;
43
+
9
44
const FileUpload : React . FC < FileUploadProps > = ( { onFilesUploaded} ) => {
10
45
const [ isDragging , setIsDragging ] = useState ( false ) ;
11
46
const fileInputRef = useRef < HTMLInputElement > ( null ) ;
@@ -16,7 +51,7 @@ const FileUpload: React.FC<FileUploadProps> = ({onFilesUploaded}) => {
16
51
reader . onload = ( e ) => {
17
52
resolve ( {
18
53
name : file . name ,
19
- path : ( file as any ) . path || file . name , // 获取完整路径
54
+ path : file . webkitRelativePath || ( file as any ) . path || file . name ,
20
55
size : file . size ,
21
56
extension : file . name . split ( '.' ) . pop ( ) || '' ,
22
57
content : e . target ?. result as string
@@ -26,10 +61,32 @@ const FileUpload: React.FC<FileUploadProps> = ({onFilesUploaded}) => {
26
61
} ) ;
27
62
} ;
28
63
64
+ const processEntries = async ( items : DataTransferItemList ) => {
65
+ const files : File [ ] = [ ] ;
66
+
67
+ await Promise . all ( Array . from ( items ) . map ( async ( item ) => {
68
+ if ( item . webkitGetAsEntry ) {
69
+ const entry = item . webkitGetAsEntry ( ) ;
70
+ if ( entry ?. isDirectory ) {
71
+ const directoryFiles = await getFilesFromDirectory ( entry as FileSystemDirectoryEntry ) ;
72
+ files . push ( ...directoryFiles ) ;
73
+ } else if ( entry ?. isFile ) {
74
+ const file = item . getAsFile ( ) ;
75
+ if ( file ) files . push ( file ) ;
76
+ }
77
+ } else {
78
+ const file = item . getAsFile ( ) ;
79
+ if ( file ) files . push ( file ) ;
80
+ }
81
+ } ) ) ;
82
+
83
+ return files ;
84
+ } ;
85
+
29
86
const handleFileDrop = async ( e : React . DragEvent ) => {
30
87
e . preventDefault ( ) ;
31
88
setIsDragging ( false ) ;
32
- const files = Array . from ( e . dataTransfer . files ) ;
89
+ const files = await processEntries ( e . dataTransfer . items ) ;
33
90
const processedFiles = await Promise . all ( files . map ( readFileContent ) ) ;
34
91
onFilesUploaded ( processedFiles ) ;
35
92
} ;
@@ -38,16 +95,13 @@ const FileUpload: React.FC<FileUploadProps> = ({onFilesUploaded}) => {
38
95
const files = Array . from ( e . target . files || [ ] ) ;
39
96
const processedFiles = await Promise . all ( files . map ( readFileContent ) ) ;
40
97
onFilesUploaded ( processedFiles ) ;
41
- // 清空input值以允许重复选择相同文件
42
98
if ( fileInputRef . current ) {
43
99
fileInputRef . current . value = '' ;
44
100
}
45
101
} ;
46
102
47
103
const handleClick = ( ) => {
48
- if ( fileInputRef . current ) {
49
- fileInputRef . current . click ( ) ;
50
- }
104
+ fileInputRef . current ?. click ( ) ;
51
105
} ;
52
106
53
107
return (
@@ -65,11 +119,12 @@ const FileUpload: React.FC<FileUploadProps> = ({onFilesUploaded}) => {
65
119
< input
66
120
type = "file"
67
121
multiple
122
+ // webkitdirectory=""
68
123
onChange = { handleFileSelect }
69
124
className = "file-input"
70
125
ref = { fileInputRef }
71
126
/>
72
- < p > 拖放AI参考代码文件到这里或点击此处选择文件 (参考上下文越完整,AI推理结果越好)</ p >
127
+ < p > 拖放AI参考代码文件/文件夹到这里或点击此处选择 (参考上下文越完整,AI推理结果越好)</ p >
73
128
</ div >
74
129
) ;
75
130
} ;
0 commit comments