File types empty for kml, kmz, and geojson
elmasrya opened this issue · comments
We are not validating at all when using "accept" we are just passing it to the file picker, we might do it in version 2.0 which will be released soon. If you want this behavior right now just write validator yourself, there are examples in readme, let me know if you have any problems
We will take a look into the empty type
@elmasrya We've investigated the issue of missing type
property.
This property represents the MIME type of file. It turns out that the package that we rely on for transforming a file input event to actual file object is only supporting a common set of MIME types, which is described here: https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types
As you can see, geojson
, kml
and kmz
extensions are not present on this list, that's why our package just fallbacks to an empty string.
If you need to get the MIME type of file, just get the name
property of a file, and then split it by the last dot, so you'll get the file extension. Then you can use a separate package like mime-types, which was specifically built for inferring the MIME type given the file extension.
When it comes to validation, @Jaaneek has already explained that you need to create a custom validator for that. There's no file type validator built into use file picker, so I wrote the one that you need:
import { Validator } from "use-file-picker/validators";
class FileTypeValidator extends Validator {
constructor(private readonly acceptedFileExtensions: string[]) {
super();
}
validateBeforeParsing(
_config: UseFilePickerConfig<any>,
plainFiles: File[]
): Promise<void> {
const fileExtensionErrors = plainFiles.reduce<
{ name: string; reason: string; causedByFile: File }[]
>((errors, currentFile) => {
const fileExtension = currentFile.name.split(".").pop();
if (!fileExtension) {
return [
...errors,
{
name: "FileTypeError",
reason: "FILE_EXTENSION_NOT_FOUND",
causedByFile: currentFile,
},
];
}
if (!this.acceptedFileExtensions.includes(fileExtension)) {
return [
...errors,
{
name: "FileTypeError",
reason: "FILE_TYPE_NOT_ACCEPTED",
causedByFile: currentFile,
},
];
}
return errors;
},
[]
);
return fileExtensionErrors.length > 0
? Promise.reject(fileExtensionErrors)
: Promise.resolve();
}
validateAfterParsing(
_config: UseFilePickerConfig<any>,
_file: FileWithPath,
_reader: FileReader
): Promise<void> {
return Promise.resolve();
}
}
You can later pass it as an argument to the hook:
const { openFilePicker, errors, plainFiles, filesContent } = useFilePicker({
validators: [
new FileTypeValidator(["geojson", "kml", "kmz"]),
],
accept: ["*.geojson","*.kml", "*.kmz"],
readAs: "Text",
});
I hope it helps! Your use case is quite common, so I'll make sure that this FileTypeValidator
is included in the next release of use file picker.
File type validator was natively shipped with v2.1.1. If you want to use it, just import it from:
import { FileTypeValidator } from 'use-file-picker/validators';
Its API hasn't changed, you can still use it the same way I've already described in this thread above.