Reputation: 141
Using @sveltejs/adapter-node: 1.0.0-next.61
and @sveltejs/kit: ^1.0.0-next.225
The following issue occurs only on the build version of the app, and not on the dev server, on which it doesn't occur.
When uploading a new file, my app keeps returning 404 regarding those newly created files as though the app is blind to those. Interestingly enough, said images are found when restarting the server.
The creation request succeeds:
The file is correctly created on the filesystem and should be loaded by the page as seen in the json response which lists all files to be loaded on the page:
However, when attempting to fetch the file, the server responds with a 404 although the path to it is correct:
Upvotes: 8
Views: 2293
Reputation: 86
I got to sort it out by serving images in base64 format. So first at all I save the uploaded images out of static
directory. Then I have an endpoint that returns the image, but that accept a parameter to apply for base64
format. Then in the html I add in the src
of the image the base64 version of it.
My directory tree looks like:
src
├── app.html
├── images
├── lib
└── routes
└── [imagePath]
└── +server.js
Then +server.js
looks like this:
import { error, json } from '@sveltejs/kit'
import fs from 'fs'
export async function GET({ url, params }) {
const format = url.searchParams.get('format') ?? ''
const { imagePath } = params
const completeImagePath = `src/images/${imagePath}`
if (fs.existsSync(completeImagePath)) {
const image = fs.readFileSync(completeImagePath)
if (format === 'base64') {
const imageBase64 = fs.readFileSync(completeImagePath, { encoding: 'base64' })
return json({ imageBase64 })
} else {
return new Response(image)
}
} else {
error(404, {
message: `Could not find ${params.imagePath}`
})
}
}
So now if we GET http://example.com/imageId.png
, for example it will return the image, but if we add format
parameter we can get the base64 code: http://example.com/imageId.png?format=base64
Then now in our .svelte
files we can load this image on base64 format and pass it in the way below:
<img src={`data:image/png;base64, ${imageBase64}`} alt="image-alt" />
Where imageBase64
has been retrieved previously.
Upvotes: 0
Reputation: 492
Actually I found two solutions but both are just workarounds to this very annoying problem.
The import way: that's quite tricky to configure it properly (read also this) and, overall, it becomes a pain if you need to import dynamic paths (with variables inside the import path) as it was in my case.
The CDN
way: use the static folder as a CDN by pointing there the webserver with a dedicated (sub)domain. This way you can link assets with success as they are "external" resources (e.g. https://cdn.mysite.com/file1.png
, https://cdn.mysite.com/file2.jpg
).
Bonus: if you choose the CDN workaround, can be a good idea to set handleFetch to bypass the external DNS resolution and keeping traffic internally.
Upvotes: 1
Reputation: 148
I fixed this problem by using an api endpoint to fetch my files. I also added some performance features. You can check the full article here: my medium article
Upvotes: 1
Reputation: 11
This problem can be solved by using a custom server with express to serve the static files. First run "npm run build" and add a server.js file into build path.
// server.js
import { handler } from './handler.js';
import express from 'express';
const app = express();
// add a route that lives separately from the SvelteKit app
app.get('/img/*', express.static('static'));
// let SvelteKit handle everything else, including serving prerendered pages and static assets
app.use(handler);
app.listen(3000, () => {
console.log('listening on port 3000');
});
Then run "node server.js" instead of "node index.js"
Upvotes: 1