19
[Express][TypeScript] Downloading files
This time, I will try downloading files.
I can download files by fs like below.
import fs from 'fs';
export function loadFile(): fs.ReadStream {
return fs.createReadStream('tmp/region.png');
}
import express from 'express';
...
import * as downloader from './files/fileDownloader';
const port = 3000;
const app = express();
...
app.get('/files/download', (req, res) => {
const stream = downloader.loadFile();
// download file as "hello.png"
res.writeHead(200, {
"Content-Type": "image/png",
"Content-Disposition": "attachment; filename=hello.png",
});
stream.on('open', () => {
console.log('Opened');
stream.pipe(res);
});
stream.on('close', () => {
console.log('Closed');
});
});
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
});
It's very simple.
After opening the stream, downloading the file is started.
After finishing the downloading, the stream is closed.
How about playing videos?
First, I try setting the url as "src" of a video element.
<!DOCTYPE html>
<html lang='en'>
<head>
<title>Hello</title>
<meta charset="utf8">
</head>
<body>
...
<video muted controls autoplay src="/files/video"></video>
<script src="./js/main.page.js"></script>
<script>Page.init()</script>
</body>
</html>
app.get('/files/video', (req, res) => {
const stream = downloader.loadVideo();
stream.on('open', () => {
console.log('Opened');
stream.pipe(res);
});
stream.on('close', () => {
console.log('Closed');
});
});
import fs from 'fs';
...
export function loadVideo(): fs.ReadStream {
return fs.createReadStream('tmp/sample.mp4');
}
I can play the video.
But I have a problem.
After loading the page, before starting the video, I must wait for downloading data first.
After donwloading, the video start playing.
But the data isn't the first one.
I think it's for getting the video information to prepare playing.
Can I avoid the first downloading or finish more quickly?
How about donwload the video and set it into the video element by TypeScript?
...
<video id="video_sample"></video>
<script src="./js/main.page.js"></script>
<script>Page.init()</script>
</body>
</html>
...
export function init() {
const targetVideo = document.getElementById('video_sample') as HTMLVideoElement;
targetVideo.muted = true;
targetVideo.controls = true;
targetVideo.autoplay = true;
fetch('files/video', {
method: 'GET',
mode: 'cors'
})
.then(res => res.blob())
.then(data => {
targetVideo.src = URL.createObjectURL(data);
})
.catch(err => console.error(err));
}
Most of the result was same as first example.
Because it also waits for downloading all of the video data first.
The difference is caching the video data, so though I replay the video after finishing the first playing, it won't download the data again.
Can I set Stream API as the source of the video element?
I couldn't find how to do that :(
If I can generate "MediaStream" or "MediaSource" from ReadableStream, I can set as "srcObject" of the video element...
Shall I use WebSocket or WebRTC?
19