mirror of
https://github.com/shishantbiswas/bknd.git
synced 2026-03-16 04:27:21 +00:00
feat: implement file acceptance validation in utils and integrate with Dropzone component
This commit is contained in:
@@ -264,6 +264,35 @@ describe("Core Utils", async () => {
|
||||
height: 512,
|
||||
});
|
||||
});
|
||||
|
||||
test("isFileAccepted", () => {
|
||||
const file = new File([""], "file.txt", {
|
||||
type: "text/plain",
|
||||
});
|
||||
expect(utils.isFileAccepted(file, "text/plain")).toBe(true);
|
||||
expect(utils.isFileAccepted(file, "text/plain,text/html")).toBe(true);
|
||||
expect(utils.isFileAccepted(file, "text/html")).toBe(false);
|
||||
|
||||
{
|
||||
const file = new File([""], "file.jpg", {
|
||||
type: "image/jpeg",
|
||||
});
|
||||
expect(utils.isFileAccepted(file, "image/jpeg")).toBe(true);
|
||||
expect(utils.isFileAccepted(file, "image/jpeg,image/png")).toBe(true);
|
||||
expect(utils.isFileAccepted(file, "image/png")).toBe(false);
|
||||
expect(utils.isFileAccepted(file, "image/*")).toBe(true);
|
||||
expect(utils.isFileAccepted(file, ".jpg")).toBe(true);
|
||||
expect(utils.isFileAccepted(file, ".jpg,.png")).toBe(true);
|
||||
expect(utils.isFileAccepted(file, ".png")).toBe(false);
|
||||
}
|
||||
|
||||
{
|
||||
const file = new File([""], "file.png");
|
||||
expect(utils.isFileAccepted(file, undefined as any)).toBe(true);
|
||||
}
|
||||
|
||||
expect(() => utils.isFileAccepted(null as any, "text/plain")).toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe("dates", () => {
|
||||
|
||||
@@ -240,3 +240,46 @@ export async function blobToFile(
|
||||
lastModified: Date.now(),
|
||||
});
|
||||
}
|
||||
|
||||
export function isFileAccepted(file: File | unknown, _accept: string | string[]): boolean {
|
||||
const accept = Array.isArray(_accept) ? _accept.join(",") : _accept;
|
||||
if (!accept || !accept.trim()) return true; // no restrictions
|
||||
if (!isFile(file)) {
|
||||
throw new Error("Given file is not a File instance");
|
||||
}
|
||||
|
||||
const name = file.name.toLowerCase();
|
||||
const type = (file.type || "").trim().toLowerCase();
|
||||
|
||||
// split on commas, trim whitespace
|
||||
const tokens = accept
|
||||
.split(",")
|
||||
.map((t) => t.trim().toLowerCase())
|
||||
.filter(Boolean);
|
||||
|
||||
// try each token until one matches
|
||||
return tokens.some((token) => {
|
||||
if (token.startsWith(".")) {
|
||||
// extension match, e.g. ".png" or ".tar.gz"
|
||||
return name.endsWith(token);
|
||||
}
|
||||
|
||||
const slashIdx = token.indexOf("/");
|
||||
if (slashIdx !== -1) {
|
||||
const [major, minor] = token.split("/");
|
||||
if (minor === "*") {
|
||||
// wildcard like "image/*"
|
||||
if (!type) return false;
|
||||
const [fMajor] = type.split("/");
|
||||
return fMajor === major;
|
||||
} else {
|
||||
// exact MIME like "image/svg+xml" or "application/pdf"
|
||||
// because of "text/plain;charset=utf-8"
|
||||
return type.startsWith(token);
|
||||
}
|
||||
}
|
||||
|
||||
// unknown token shape, ignore
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -9,8 +9,8 @@ import {
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from "react";
|
||||
import { isFileAccepted } from "bknd/utils";
|
||||
import { type FileWithPath, useDropzone } from "./use-dropzone";
|
||||
import { checkMaxReached } from "./helper";
|
||||
import { DropzoneInner } from "./DropzoneInner";
|
||||
@@ -173,12 +173,14 @@ export function Dropzone({
|
||||
|
||||
return specs.every((spec) => {
|
||||
if (spec.kind !== "file") {
|
||||
console.log("not a file", spec.kind);
|
||||
console.warn("file not accepted: not a file", spec.kind);
|
||||
return false;
|
||||
}
|
||||
if (allowedMimeTypes && allowedMimeTypes.length > 0) {
|
||||
console.log("not allowed mimetype", spec.type);
|
||||
return allowedMimeTypes.includes(spec.type);
|
||||
if (!isFileAccepted(i, allowedMimeTypes)) {
|
||||
console.warn("file not accepted: not allowed mimetype", spec.type);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user