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.
CodePudding user response:
As @Stephane suggest, put your files under statics
folder. This way you can serve directly through a reverse proxy, like Nginx
CodePudding user response:
You can use import.meta.glob
for this.
export async function get({ params }){
const file = `./${params.file}.pdf`;
const pdfs = import.meta.glob(('./*.pdf', { as: 'raw' });
const pdf = pdfs[file];
return {
status:200,
headers: {
"Content-type" : "application/pdf",
"Content-Disposition": "attachment; filename=" params.file ".pdf"
},
body: pdf
}
}
The import.meta.glob
in combination with the as: 'raw'
option will effectively embed the contents of each file in your resulting code. (this is purely server side so no worries about shipping to much to the client)
Note that this of course means that only files present during build can be served this way.