| | import { base } from "$app/paths"; |
| |
|
| | export interface AttachmentLoadResult { |
| | files: File[]; |
| | errors: string[]; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | function parseAttachmentUrls(searchParams: URLSearchParams): string[] { |
| | const urls: string[] = []; |
| |
|
| | |
| | const attachmentParams = searchParams.getAll("attachments"); |
| |
|
| | for (const param of attachmentParams) { |
| | |
| | const splitUrls = param.split(",").map((url) => url.trim()); |
| | urls.push(...splitUrls); |
| | } |
| |
|
| | |
| | return urls.filter((url) => url.length > 0); |
| | } |
| |
|
| | |
| | |
| | |
| | function extractFilename(url: string, contentDisposition?: string | null): string { |
| | |
| | if (contentDisposition) { |
| | const match = contentDisposition.match(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/); |
| | if (match && match[1]) { |
| | return match[1].replace(/['"]/g, ""); |
| | } |
| | } |
| |
|
| | |
| | try { |
| | const urlObj = new URL(url); |
| | const pathname = urlObj.pathname; |
| | const segments = pathname.split("/"); |
| | const lastSegment = segments[segments.length - 1]; |
| |
|
| | if (lastSegment && lastSegment.length > 0) { |
| | return decodeURIComponent(lastSegment); |
| | } |
| | } catch { |
| | |
| | } |
| |
|
| | return "attachment"; |
| | } |
| |
|
| | |
| | |
| | |
| | export async function loadAttachmentsFromUrls( |
| | searchParams: URLSearchParams |
| | ): Promise<AttachmentLoadResult> { |
| | const urls = parseAttachmentUrls(searchParams); |
| |
|
| | if (urls.length === 0) { |
| | return { files: [], errors: [] }; |
| | } |
| |
|
| | const files: File[] = []; |
| | const errors: string[] = []; |
| |
|
| | await Promise.all( |
| | urls.map(async (url) => { |
| | try { |
| | |
| | const proxyUrl = `${base}/api/fetch-url?${new URLSearchParams({ url })}`; |
| | const response = await fetch(proxyUrl); |
| |
|
| | if (!response.ok) { |
| | const errorText = await response.text(); |
| | errors.push(`Failed to fetch ${url}: ${errorText}`); |
| | return; |
| | } |
| |
|
| | const blob = await response.blob(); |
| | const contentDisposition = response.headers.get("content-disposition"); |
| | const filename = extractFilename(url, contentDisposition); |
| |
|
| | |
| | const file = new File([blob], filename, { |
| | type: blob.type || "application/octet-stream", |
| | }); |
| |
|
| | files.push(file); |
| | } catch (err) { |
| | const message = err instanceof Error ? err.message : "Unknown error"; |
| | errors.push(`Failed to load ${url}: ${message}`); |
| | console.error(`Error loading attachment from ${url}:`, err); |
| | } |
| | }) |
| | ); |
| |
|
| | return { files, errors }; |
| | } |
| |
|