Search code examples
restsveltefssveltekit

How to Return File from SvelteKit Endpoint


I am trying to serve a PDF file that my SvelteKit app generates and allow a user to download it from an endpoint.

My project structure looks like this:

---------------------
/src/routes/downloads
---------------------
[file].ts
ABC.pdf
XYZ.pdf

My [file].ts endpoint looks like this:

import fs from 'fs'

// ----- GET -----
export async function get({ params }){
  //console.log(params.file) -> ABC

  var pdf = fs.readFileSync('./src/routes/downloads/'+params.file+'.pdf')

  return{
    status:200,
    headers: {
      "Content-type" : "application/pdf",
      "Content-Disposition": "attachment; filename="+params.file+".pdf"
    },
    body: pdf
  }
}

So then when I hit http://localhost:3000/downloads/ABC, the PDF file named ABC.pdf downloads.

But my readFileSync path isn't something that's going to work on production. As far as I know, there is no /src/routes folder.

How do I serve my file from a http://localhost:3000 url? Everything I've tried yields a 404 and it can't find the file. I'm also open to a different way of handling this scenario. This is just my best guess of how to do this in SvelteKit.


Solution

  • The recommended way to do this, for adapter-node, is to place your application data in a new folder under your project's root directory (ie. alongside /src and /static). You can then read files with a relative path: fs.readFile('./my-app-data/foo.txt').

    For deployment, you just have to make sure to execute node build from the project root, as this guarantees that you have the same working directory during both development and production.

    The static folder works, but it is not meant to carry application data—files in this folder represent new routes that are served directly to users, so this is not desirable if your generated files must be protected in any way. Even if they're meant to be public files, it still blurs what is supposed to be production and source data: should a new deploy overwrite all the files in static? If you're not careful, a naming clash could mean overwriting production data.