diff --git a/DrSousan.Api/Program.cs b/DrSousan.Api/Program.cs index acea375..f092e45 100644 --- a/DrSousan.Api/Program.cs +++ b/DrSousan.Api/Program.cs @@ -589,7 +589,7 @@ app.MapPost("/api/upload", async (HttpRequest request, IWebHostEnvironment env) if (!request.HasFormContentType || !request.Form.Files.Any()) return Results.BadRequest("No file provided."); var file = request.Form.Files[0]; - var allowed = new[] { ".jpg", ".jpeg", ".png", ".webp", ".gif" }; + var allowed = new[] { ".jpg", ".jpeg", ".png", ".webp", ".gif", ".svg", ".ico" }; var ext = Path.GetExtension(file.FileName).ToLowerInvariant(); if (!allowed.Contains(ext)) return Results.BadRequest("File type not allowed."); var uploadsDir = Path.Combine(env.WebRootPath, "uploads"); diff --git a/DrSousan.Api/wwwroot/admin/index.html b/DrSousan.Api/wwwroot/admin/index.html index c45a725..2e69a28 100644 --- a/DrSousan.Api/wwwroot/admin/index.html +++ b/DrSousan.Api/wwwroot/admin/index.html @@ -1690,6 +1690,9 @@ const cropper = { function openCropper(inputId, previewId, file) { cropper.inputId = inputId; cropper.previewId = previewId; + // Preserve original file type so PNG stays PNG, WebP stays WebP, etc. + cropper.mimeType = file.type || 'image/jpeg'; + cropper.fileName = file.name || 'upload'; const reader = new FileReader(); reader.onload = e => { const img = new Image(); @@ -1831,7 +1834,8 @@ async function applyCrop() { btn.disabled = true; try { const fd = new FormData(); - fd.append('file', new File([blob], 'crop.jpg', {type:'image/jpeg'})); + const ext = _inputId && cropper.mimeType ? cropper.mimeType.split('/')[1].replace('jpeg','jpg') : 'jpg'; + fd.append('file', new File([blob], `crop.${ext}`, {type: cropper.mimeType || 'image/jpeg'})); const r = await fetch('/api/upload', {method:'POST', headers:{'Authorization':`Bearer ${token}`}, body:fd}); if (!r.ok) throw new Error(await r.text()); const { url } = await r.json(); @@ -1840,13 +1844,16 @@ async function applyCrop() { toast('تصویر با موفقیت آپلود شد ✓'); } catch(e) { toast('خطا در آپلود: '+e.message,'error'); } finally { btn.innerHTML=orig; btn.disabled=false; } - }, 'image/jpeg', 0.92); + // Use original mime type; only pass quality for lossy formats + const mime = cropper.mimeType || 'image/jpeg'; + const quality = (mime === 'image/jpeg' || mime === 'image/webp') ? 0.92 : undefined; + }, mime, quality); } async function uploadImage(inputId, previewId) { const fileInput = document.createElement('input'); fileInput.type = 'file'; - fileInput.accept = 'image/jpeg,image/png,image/webp,image/gif'; + fileInput.accept = 'image/jpeg,image/png,image/webp,image/gif,image/svg+xml,image/x-icon,image/vnd.microsoft.icon'; fileInput.onchange = () => { const file = fileInput.files[0]; if (!file) return;