Add error message to user if trying to upload too big image

This commit is contained in:
Kalle
2026-01-14 20:59:57 +02:00
parent 2522276be7
commit 41fadb20fe
3 changed files with 49 additions and 5 deletions

View File

@@ -1,5 +1,4 @@
import type { FileUpload } from "@remix-run/form-data-parser"; import type { FileUpload } from "@remix-run/form-data-parser";
import { parseFormData as parseMultipartFormData } from "@remix-run/form-data-parser";
import { nanoid } from "nanoid"; import { nanoid } from "nanoid";
import type { ActionFunction } from "react-router"; import type { ActionFunction } from "react-router";
import { redirect } from "react-router"; import { redirect } from "react-router";
@@ -14,6 +13,7 @@ import {
errorToastIfFalsy, errorToastIfFalsy,
parseFormData, parseFormData,
parseRequestPayload, parseRequestPayload,
safeParseMultipartFormData,
} from "~/utils/remix.server"; } from "~/utils/remix.server";
import { userArtPage } from "~/utils/urls"; import { userArtPage } from "~/utils/urls";
import { NEW_ART_EXISTING_SEARCH_PARAM_KEY } from "../art-constants"; import { NEW_ART_EXISTING_SEARCH_PARAM_KEY } from "../art-constants";
@@ -86,7 +86,7 @@ export const action: ActionFunction = async ({ request }) => {
return null; return null;
}; };
const formData = await parseMultipartFormData( const formData = await safeParseMultipartFormData(
request, request,
// 5MB // 5MB
{ maxFileSize: 5 * 1024 * 1024 }, { maxFileSize: 5 * 1024 * 1024 },

View File

@@ -1,5 +1,4 @@
import type { FileUpload } from "@remix-run/form-data-parser"; import type { FileUpload } from "@remix-run/form-data-parser";
import { parseFormData } from "@remix-run/form-data-parser";
import type { ActionFunctionArgs } from "react-router"; import type { ActionFunctionArgs } from "react-router";
import { redirect } from "react-router"; import { redirect } from "react-router";
import { z } from "zod"; import { z } from "zod";
@@ -14,6 +13,7 @@ import {
badRequestIfFalsy, badRequestIfFalsy,
errorToastIfFalsy, errorToastIfFalsy,
parseSearchParams, parseSearchParams,
safeParseMultipartFormData,
} from "~/utils/remix.server"; } from "~/utils/remix.server";
import { teamPage, tournamentOrganizationPage } from "~/utils/urls"; import { teamPage, tournamentOrganizationPage } from "~/utils/urls";
import * as ImageRepository from "../ImageRepository.server"; import * as ImageRepository from "../ImageRepository.server";
@@ -57,7 +57,7 @@ export const action = async ({ request }: ActionFunctionArgs) => {
return null; return null;
}; };
const formData = await parseFormData(request, uploadHandler); const formData = await safeParseMultipartFormData(request, uploadHandler);
const imgSrc = formData.get("img") as string | null; const imgSrc = formData.get("img") as string | null;
invariant(imgSrc); invariant(imgSrc);

View File

@@ -291,6 +291,50 @@ export function privatelyCachedJson<T>(dataValue: T) {
}); });
} }
const MAX_FILE_SIZE_BYTES = 5 * 1024 * 1024;
type FileUploadHandler = (
fileUpload: FileUpload,
) => Promise<string | null | undefined>;
type ParseFormDataOptions = { maxFileSize?: number };
export function safeParseMultipartFormData(
request: Request,
uploadHandler?: FileUploadHandler,
): Promise<FormData>;
export function safeParseMultipartFormData(
request: Request,
options?: ParseFormDataOptions,
uploadHandler?: FileUploadHandler,
): Promise<FormData>;
export async function safeParseMultipartFormData(
request: Request,
optionsOrHandler?: ParseFormDataOptions | FileUploadHandler,
uploadHandler?: FileUploadHandler,
): Promise<FormData> {
try {
if (typeof optionsOrHandler === "function") {
return await parseMultipartFormData(request, optionsOrHandler);
}
return await parseMultipartFormData(
request,
optionsOrHandler,
uploadHandler,
);
} catch (err) {
if (
err instanceof Error &&
err.cause instanceof Error &&
err.cause.name === "MaxFileSizeExceededError"
) {
throw errorToastRedirect(
`File size exceeds maximum allowed size of ${MAX_FILE_SIZE_BYTES / 1024 / 1024}MB`,
);
}
throw err;
}
}
export async function uploadImageIfSubmitted({ export async function uploadImageIfSubmitted({
request, request,
fileNamePrefix, fileNamePrefix,
@@ -318,7 +362,7 @@ export async function uploadImageIfSubmitted({
let formData: FormData; let formData: FormData;
try { try {
formData = await parseMultipartFormData(request, uploadHandler); formData = await safeParseMultipartFormData(request, uploadHandler);
const imgSrc = formData.get("img") as string | null; const imgSrc = formData.get("img") as string | null;
if (!imgSrc) { if (!imgSrc) {
throw new TypeError("No image submitted"); throw new TypeError("No image submitted");