@@ -37,12 +37,167 @@ export class DeleteEvent extends ModelEvent {
3737 }
3838}
3939
40+ // Mapping of file extensions to browser-reported MIME types
41+ // as it's not yet supported by filepond, see:
42+ // https://github.com/pqina/filepond-plugin-file-validate-type/issues/13
43+ const EXTENSION_TO_MIME_TYPE : Record < string , string > = {
44+ // Images
45+ ".png" : "image/png" ,
46+ ".jpg" : "image/jpeg" ,
47+ ".jpeg" : "image/jpeg" ,
48+ ".gif" : "image/gif" ,
49+ ".svg" : "image/svg+xml" ,
50+ ".webp" : "image/webp" ,
51+ ".bmp" : "image/bmp" ,
52+ ".ico" : "image/x-icon" ,
53+ ".tiff" : "image/tiff" ,
54+ ".tif" : "image/tiff" ,
55+ ".avif" : "image/avif" ,
56+
57+ // Video
58+ ".mp4" : "video/mp4" ,
59+ ".webm" : "video/webm" ,
60+ ".mov" : "video/quicktime" ,
61+ ".mkv" : "video/x-matroska" ,
62+ ".avi" : "video/x-msvideo" ,
63+ ".wmv" : "video/x-ms-wmv" ,
64+ ".flv" : "video/x-flv" ,
65+
66+ // Audio
67+ ".mp3" : "audio/mpeg" ,
68+ ".wav" : "audio/wav" ,
69+ ".ogg" : "audio/ogg" ,
70+ ".oga" : "audio/ogg" ,
71+ ".m4a" : "audio/mp4" ,
72+ ".aac" : "audio/aac" ,
73+ ".flac" : "audio/flac" ,
74+
75+ // Text / documents
76+ ".txt" : "text/plain" ,
77+ ".md" : "text/markdown" ,
78+ ".rtf" : "application/rtf" ,
79+ ".pdf" : "application/pdf" ,
80+
81+ // Structured data (browser-compatible)
82+ ".json" : "application/json" ,
83+ ".xml" : "text/xml" ,
84+ ".csv" : "text/csv" ,
85+ ".tsv" : "text/tab-separated-values" ,
86+ ".yaml" : "text/yaml" ,
87+ ".yml" : "text/yaml" ,
88+
89+ // Web / code
90+ ".html" : "text/html" ,
91+ ".htm" : "text/html" ,
92+ ".css" : "text/css" ,
93+ ".js" : "text/javascript" ,
94+ ".mjs" : "text/javascript" ,
95+ ".ts" : "application/typescript" ,
96+ ".jsx" : "text/jsx" ,
97+ ".tsx" : "text/tsx" ,
98+ ".wasm" : "application/wasm" ,
99+
100+ // Office documents
101+ ".doc" : "application/msword" ,
102+ ".docx" : "application/vnd.openxmlformats-officedocument.wordprocessingml.document" ,
103+ ".xls" : "application/vnd.ms-excel" ,
104+ ".xlsb" : "application/vnd.ms-excel.sheet.binary.macroenabled.12" ,
105+ ".xlsx" : "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" ,
106+ ".ppt" : "application/vnd.ms-powerpoint" ,
107+ ".pptx" : "application/vnd.openxmlformats-officedocument.presentationml.presentation" ,
108+ ".odt" : "application/vnd.oasis.opendocument.text" ,
109+ ".ods" : "application/vnd.oasis.opendocument.spreadsheet" ,
110+ ".odp" : "application/vnd.oasis.opendocument.presentation" ,
111+
112+ // Archives
113+ ".zip" : "application/zip" ,
114+ ".tar" : "application/x-tar" ,
115+ ".gz" : "application/gzip" ,
116+ ".tgz" : "application/gzip" ,
117+ ".bz2" : "application/x-bzip2" ,
118+ ".xz" : "application/x-xz" ,
119+ ".7z" : "application/x-7z-compressed" ,
120+ ".rar" : "application/vnd.rar" ,
121+
122+ // Fonts
123+ ".ttf" : "font/ttf" ,
124+ ".otf" : "font/otf" ,
125+ ".woff" : "font/woff" ,
126+ ".woff2" : "font/woff2" ,
127+
128+ // Executables / binaries
129+ ".exe" : "application/vnd.microsoft.portable-executable" ,
130+ ".dll" : "application/vnd.microsoft.portable-executable" ,
131+ ".bin" : "application/octet-stream" ,
132+ ".dmg" : "application/x-apple-diskimage" ,
133+ ".pkg" : "application/octet-stream" ,
134+ ".deb" : "application/vnd.debian.binary-package" ,
135+ ".rpm" : "application/x-rpm" ,
136+
137+ // Columnar / big data
138+ ".parquet" : "application/octet-stream" , // browsers do NOT emit application/parquet
139+ ".arrow" : "application/octet-stream" ,
140+ ".feather" : "application/octet-stream" ,
141+ ".orc" : "application/octet-stream" ,
142+
143+ // Scientific / numerical
144+ ".npy" : "application/octet-stream" ,
145+ ".npz" : "application/octet-stream" ,
146+ ".mat" : "application/octet-stream" ,
147+ ".h5" : "application/octet-stream" ,
148+ ".hdf5" : "application/octet-stream" ,
149+ ".zarr" : "application/octet-stream" ,
150+
151+ // R ecosystem
152+ ".rds" : "application/octet-stream" ,
153+ ".rda" : "application/octet-stream" ,
154+ ".rdata" : "application/octet-stream" ,
155+
156+ // Notebooks
157+ ".ipynb" : "application/json" ,
158+
159+ // ML models / artifacts
160+ ".pkl" : "application/octet-stream" ,
161+ ".pickle" : "application/octet-stream" ,
162+ ".joblib" : "application/octet-stream" ,
163+ ".onnx" : "application/octet-stream" ,
164+ ".pt" : "application/octet-stream" ,
165+ ".pth" : "application/octet-stream" ,
166+ ".h5model" : "application/octet-stream" ,
167+
168+ // Vector
169+ ".shp" : "application/octet-stream" ,
170+ ".shx" : "application/octet-stream" ,
171+ ".dbf" : "application/octet-stream" ,
172+ ".geojson" : "application/geo+json" ,
173+ ".gpkg" : "application/octet-stream" ,
174+
175+ // Raster
176+ ".geotiff" : "image/tiff" ,
177+ ".asc" : "text/plain" ,
178+ }
179+
40180export class FileDropperView extends InputWidgetView {
41181 declare model : FileDropper
42182 declare input_el : HTMLInputElement
43183 _file_pond : any | null = null
44184 _transfer_in_process : string | null = null
45185
186+ private extensionsToMimeTypes ( types : string [ ] ) : string [ ] {
187+ return types . map ( type => {
188+ // MIME types, including wildcards like "image/*"
189+ if ( type . includes ( "/" ) ) {
190+ return type
191+ }
192+ // Guessing it's an extension
193+ if ( type . startsWith ( "." ) ) {
194+ const lowerType = type . toLowerCase ( )
195+ return EXTENSION_TO_MIME_TYPE [ lowerType ] || type
196+ }
197+ return type
198+ } )
199+ }
200+
46201 override initialize ( ) : void {
47202 super . initialize ( )
48203 const { previews} = this . model
@@ -61,7 +216,7 @@ export class FileDropperView extends InputWidgetView {
61216 const { disabled, layout, max_file_size, max_files, max_total_file_size, multiple} = this . model . properties
62217 this . on_change ( [ disabled , max_file_size , max_files , max_total_file_size , multiple , layout ] , ( ) => {
63218 this . _file_pond ?. setOptions ( {
64- acceptedFileTypes : this . model . accepted_filetypes ,
219+ acceptedFileTypes : this . extensionsToMimeTypes ( this . model . accepted_filetypes ) ,
65220 allowMultiple : this . model . multiple ,
66221 disabled : this . model . disabled ,
67222 maxFiles : this . model . max_files ,
@@ -91,9 +246,8 @@ export class FileDropperView extends InputWidgetView {
91246
92247 override render ( ) : void {
93248 super . render ( )
94-
95249 this . _file_pond = ( window as any ) . FilePond . create ( this . input_el , {
96- acceptedFileTypes : this . model . accepted_filetypes ,
250+ acceptedFileTypes : this . extensionsToMimeTypes ( this . model . accepted_filetypes ) ,
97251 allowMultiple : this . model . multiple ,
98252 credits : false ,
99253 disabled : this . model . disabled ,
0 commit comments