feat(photo-upload): Limits hochschrauben fuer Tablet-Fotos
All checks were successful
Build & Publish Docker Image / build-and-push (push) Successful in 2m16s
All checks were successful
Build & Publish Docker Image / build-and-push (push) Successful in 2m16s
Tablet- und iPad-Pro-Kameras liefern JPEGs/HEICs bis 15 MB. Mit den alten 8-/10-MB-Limits scheiterte das Upload beim SvelteKit-Body-Parser mit "Multipart erwartet" (undurchsichtiger Fehler, weil SvelteKit den Body frueher abweist als unser Endpoint-Check). - Endpoint MAX_BYTES: 8 -> 20 MB - BODY_SIZE_LIMIT: 10 -> 25 MB (mit Multipart-Overhead) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -17,9 +17,10 @@ services:
|
|||||||
- GEMINI_API_KEY=${GEMINI_API_KEY:-}
|
- GEMINI_API_KEY=${GEMINI_API_KEY:-}
|
||||||
- GEMINI_MODEL=${GEMINI_MODEL:-gemini-2.5-flash}
|
- GEMINI_MODEL=${GEMINI_MODEL:-gemini-2.5-flash}
|
||||||
- GEMINI_TIMEOUT_MS=${GEMINI_TIMEOUT_MS:-20000}
|
- GEMINI_TIMEOUT_MS=${GEMINI_TIMEOUT_MS:-20000}
|
||||||
# adapter-node-Default ist 512 KB; Rezept-Fotos koennen bis 8 MB sein.
|
# adapter-node-Default ist 512 KB. Tablet- und iPad-Pro-Kameras liefern
|
||||||
# Multipart-Overhead einrechnen -> 10 MB gibt etwas Puffer.
|
# JPEGs/HEICs bis 15 MB. Endpoint-Limit ist 20 MB; hier 25 MB fuer den
|
||||||
- BODY_SIZE_LIMIT=10000000
|
# Multipart-Overhead.
|
||||||
|
- BODY_SIZE_LIMIT=25000000
|
||||||
depends_on:
|
depends_on:
|
||||||
- searxng
|
- searxng
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|||||||
@@ -6,7 +6,11 @@ import { pickRandomPhrase } from '$lib/server/ai/description-phrases';
|
|||||||
import { createRateLimiter } from '$lib/server/ai/rate-limit';
|
import { createRateLimiter } from '$lib/server/ai/rate-limit';
|
||||||
import type { Ingredient, Step } from '$lib/types';
|
import type { Ingredient, Step } from '$lib/types';
|
||||||
|
|
||||||
const MAX_BYTES = 8 * 1024 * 1024;
|
// 20 MB deckt auch Tablet- und iPad-Pro-Fotos ab (oft 10-15 MB JPEG/HEIC).
|
||||||
|
// Muss zusammen mit BODY_SIZE_LIMIT (docker-compose.prod.yml) hochgezogen werden --
|
||||||
|
// SvelteKit rejected groessere Bodies frueher und wirft dann undurchsichtige
|
||||||
|
// "Multipart erwartet"-Fehler.
|
||||||
|
const MAX_BYTES = 20 * 1024 * 1024;
|
||||||
const ALLOWED_MIME = new Set([
|
const ALLOWED_MIME = new Set([
|
||||||
'image/jpeg',
|
'image/jpeg',
|
||||||
'image/png',
|
'image/png',
|
||||||
|
|||||||
@@ -70,8 +70,8 @@ describe('POST /api/recipes/extract-from-photo', () => {
|
|||||||
expect(body.recipe.id).toBeNull();
|
expect(body.recipe.id).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('413 when file exceeds 8 MB', async () => {
|
it('413 when file exceeds 20 MB', async () => {
|
||||||
const big = Buffer.alloc(9 * 1024 * 1024);
|
const big = Buffer.alloc(21 * 1024 * 1024);
|
||||||
const fd = new FormData();
|
const fd = new FormData();
|
||||||
fd.append('photo', new Blob([new Uint8Array(big)], { type: 'image/jpeg' }));
|
fd.append('photo', new Blob([new Uint8Array(big)], { type: 'image/jpeg' }));
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
|||||||
Reference in New Issue
Block a user