Deno seems targeting text files, but I also need to serve image files for the website.
3 Answers
You can use send()
The function
send()
is designed to serve static content as part of a middleware function. In the most straight forward usage, a root is provided and requests provided to the function are fulfilled with files from the local file system relative to the root from the requested path.
const app = new Application();
app.use(async (context) => {
await send(context, context.request.url.pathname, {
root: `${Deno.cwd()}/static`
});
});
await app.listen({ port: 8000 });
With the following directory structure:
static/
image.jpg
server.js
You can access the image by going to http://localhost:8000/image.jpg

- 37,983
- 8
- 84
- 98
Basically, you just need to set the correct headers for your image type, and supply the image data as a Unit8Array
:
In your middleware:
app.use(async (ctx, next) => {
// ...
const imageBuf = await Deno.readFile(pngFilePath);
ctx.response.body = imageBuf;
ctx.response.headers.set('Content-Type', 'image/png');
});
Here's a complete working example, which will download a sample image (the digitized version of the hand-drawn deno logo) and serve it at http://localhost:8000/image
, and display "Hello world" at all other addresses. The run options are in the comment on the first line:
server.ts
// deno run --allow-net=localhost:8000,deno.land --allow-read=deno_logo.png --allow-write=deno_logo.png server.ts
import {Application} from 'https://deno.land/x/oak@v5.3.1/mod.ts';
import {exists} from 'https://deno.land/std@0.59.0/fs/exists.ts';
// server listen options
const listenOptions = {
hostname: 'localhost',
port: 8000,
};
// sample image
const imageFilePath = './deno_logo.png';
const imageSource = 'https://deno.land/images/deno_logo.png';
const ensureLocalFile = async (localPath: string, url: string): Promise<void> => {
const fileExists = await exists(localPath);
if (fileExists) return;
console.log(`Downloading ${url} to ${localPath}`);
const response = await fetch(url);
if (!response.ok) throw new Error('Response not OK');
const r = response.body?.getReader;
const buf = new Uint8Array(await response.arrayBuffer());
await Deno.writeFile(imageFilePath, buf);
console.log('File saved');
};
await ensureLocalFile(imageFilePath, imageSource);
const app = new Application();
app.use(async (ctx, next) => {
// only match /image
if (ctx.request.url.pathname !== '/image') {
await next(); // pass control to next middleware
return;
}
const imageBuf = await Deno.readFile(imageFilePath);
ctx.response.body = imageBuf;
ctx.response.headers.set('Content-Type', 'image/png');
});
// default middleware
app.use((ctx) => {
ctx.response.body = "Hello world";
});
// log info about server
app.addEventListener('listen', ev => {
const defaultPortHttp = 80;
const defaultPortHttps = 443;
let portString = `:${ev.port}`;
if (
(ev.secure && ev.port === defaultPortHttps)
|| (!ev.secure && ev.port === defaultPortHttp)
) portString = '';
console.log(`Listening at http${ev.secure ? 's' : ''}://${ev.hostname ?? '0.0.0.0'}${portString}`);
console.log('Use ctrl+c to stop\n');
});
await app.listen(listenOptions);

- 27,667
- 4
- 38
- 62
Register middleware like this:
// serve static files
app.use(async (context, next) => {
try {
await context.send({
root: `${Deno.cwd()}/wwwroot/static`,
index: "index.html",
});
} catch {
await next();
}
});

- 42,091
- 47
- 181
- 266