apisvelteprismasveltekit

How do I return an image from my sveltekit api to the client?


I am trying to display an image from my server api to my client. I know that the server is getting the image but I am not able to send it back to the client. When I run the function I am getting the attachment in the server. I can console log it and see it. Also the server gives me the follow error: Invalid response from route /api/attachment: handler should return a Response object. So I am just unsure how to return this as a response object and be able to see it on the client. The server is not a +page.server.js it is just a +server.js located in the routes/api folder.

/** @type {import('./$types').RequestHandler} */
export async function GET({ url }) {
    const id = Number(url.searchParams.get('id'))
    try {
        const attachment = await prisma.TurnReport_Attachments.findUnique({
            where: {
                attachment_id: id
            },
        });
        console.log(attachment)
        const headers = {
            'Content-Type': attachment.content_type,
            'Content-Length': attachment.content_length.toString(),
        };

        if (!attachment) {
            // If attachment with the given ID is not found, return 404 error
            return {
                status: 404,
                body: { message: 'Attachment not found'},
            };
        }
        return {
            status: 200,
            headers,
            body: attachment.data,
        };
    } catch (error) {
        console.error(error);
        return {
            status: 500,
            body: { message: 'Internal server error' },
        };
    }
}

I am trying to open the image in a new tab. The function does call the correct method on the server and opens the new tab. Here is my client side function:

async function getAttachment(id) {
        const response = await fetch(`/api/attachment?id=${id}`, {
            method: 'GET'
        });
        let result = await response
        console.log(result);
        const blob = await response.blob();
        console.log(blob)
        const urlObject = URL.createObjectURL(blob);
        window.open(urlObject, '_blank');
    }

Solution

  • Use setHeaders and return a Response object instead:

    import { error } from '@sveltejs/kit';
    
    export async function GET({ setHeaders, url }) {
        const id = Number(url.searchParams.get('id'));
        try {
            const attachment = {}; // code goes here
    
            if (!attachment) {
                // If attachment with the given ID is not found, return 404 error
                throw error(404, 'Attachment not found');
            }
            setHeaders({
                'Content-Type': attachment.content_type,
                'Content-Length': attachment.content_length.toString()
            });
            return new Response(attachment);
        } catch (error) {
        throw error(500, "Internal server error")
        }
    }
    

    Incidentally also use the error helper, which will create a Response object for you.