How to server static files from folder & Upload file save on this folder. #450
Unanswered
vimalmistry
asked this question in
Q&A
Replies: 5 comments 2 replies
|
That snippet works for small files only - if you reach GB of data you have to properly stream the data - and really, you kind of always should stream! |
0 replies
|
Look at examples/VideoStreamer.js instead - it shows how you can properly stream huge files with minimal backpressure. |
0 replies
|
I just published a small library to serve static files based on this VideoStreamer example, you can check it out here https://www.npmjs.com/package/uwebsocket-serve |
1 reply
|
serve static is using |
1 reply
|
I made this: export const getContentType = (filePath: string) => {
const mimeTypes = {
'.html': 'text/html',
'.css': 'text/css',
'.js': 'application/javascript',
'.json': 'application/json',
'.jpg': 'image/jpeg',
'.jpeg': 'image/jpeg',
'.png': 'image/png',
'.gif': 'image/gif',
'.svg': 'image/svg+xml',
'.webp': 'image/webp',
'.avif': 'image/avif',
'.mp4': 'video/mp4',
'.mp3': 'audio/mp3',
'.ogg': 'audio/ogg',
'.wav': 'audio/wav',
'.pdf': 'application/pdf',
'.txt': 'text/plain',
'.zip': 'application/zip',
'.tar': 'application/x-tar',
'.gz': 'application/gzip',
'.xml': 'application/xml',
'.csv': 'text/csv',
'.rar': 'application/x-rar-compressed',
'.7z': 'application/x-7z-compressed',
'.woff': 'font/woff',
'.woff2': 'font/woff2',
'.ttf': 'font/ttf',
'.otf': 'font/otf',
'.eot': 'application/vnd.ms-fontobject',
'.mkv': 'video/x-matroska',
'.flv': 'video/x-flv',
'.ico': 'image/x-icon',
'.mpg': 'video/mpeg',
'.webm': 'video/webm',
'.jsonld': 'application/ld+json',
'.ics': 'text/calendar',
'.rtf': 'application/rtf',
'.md': 'text/markdown',
'.xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'.xls': 'application/vnd.ms-excel',
'.docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'.doc': 'application/msword',
'.pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
'.ppt': 'application/vnd.ms-powerpoint',
} as const;
const extname = path.extname(filePath).toLowerCase() as keyof typeof mimeTypes;
return mimeTypes[extname] || 'application/octet-stream';
}
export const serveStatic = async (res: HttpResponse, req: HttpRequest) => {
try {
let aborted = false;
res.onAborted(() => {
aborted = true;
});
const range = req.getHeader('range');
const filePath = path.join(__dirname, '..', '..', req.getUrl());
await fs.promises.access(filePath, fs.constants.F_OK);
const stat = await fs.promises.stat(filePath);
const fileSize = stat.size;
const contentType = getContentType(filePath) as string;
if (range) {
const [start, end] = range.replace(/bytes=/, '').split('-').map(Number);
const chunkStart = start || 0;
const chunkEnd = end || fileSize - 1;
if (chunkStart >= fileSize || chunkEnd >= fileSize) {
res.cork(() => {
res.writeStatus('416').end();
})
return;
}
const stream = fs.createReadStream(filePath, { start: chunkStart, end: chunkEnd });
res.cork(() => {
res.writeStatus('206')
.writeHeader('Access-Control-Allow-Origin', '*')
.writeHeader('Content-Type', contentType)
.writeHeader('Content-Length', `bytes ${chunkStart}-${chunkEnd}/${fileSize}`)
.writeHeader('Content-Length', `${chunkEnd - chunkStart + 1}`)
.writeHeader('Accept-Range', 'bytes')
})
stream.on('data', (chunk) => {
if (!aborted) res.cork(() => { res.write(chunk) })
});
stream.on('end', () => {
if (!aborted) res.cork(() => { res.end() })
});
stream.on('error', () => {
if (!aborted) res.cork(() => { res.writeStatus('500').end() })
});
} else {
res.cork(() => {
res.writeStatus('200')
.writeHeader('Access-Control-Allow-Origin', '*')
.writeHeader('Content-Type', contentType)
.writeHeader('Content-Length', `${fileSize}`)
.writeHeader('Cache-Control', 'public, max-age=3600')
.writeHeader('Last-Modified', stat.mtime.toUTCString())
})
const stream = fs.createReadStream(filePath);
stream.on('data', (chunk) => {
if (!aborted) res.cork(() => { res.write(chunk) })
});
stream.on('end', () => {
if (!aborted) res.cork(() => { res.end() })
});
stream.on('error', () => {
if (!aborted) res.cork(() => { res.writeStatus('500').end() })
});
}
} catch (error: any) {
console.log(error);
res.cork(() => { res.writeStatus('404').end('File not found') });
}
}
App.get('/public/*', serveStatic);
//modify filePath to your original path.
//I believe this will handle large file, and also streams etc, i also made a function to attach form-data to req.files, and json to req.body, don't know if that is needed. |
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
I am stuck at following problem
My app have 4 api so I don't want to manage another server for this :)
Thank you.
All reactions