Reputation: 11808
I need to stream 2 binary files from the filesystem from a Hono app to another Hono app.
Doing just one file is very easy with Bun and Hono Streaming API.
// Streaming app
import { Hono } from "hono";
import { stream } from "hono/streaming";
const app = new Hono();
app.get("/", (c) => {
return stream(c, async (stream) => {
// Write a process to be executed when aborted.
stream.onAbort(() => {
console.log("Aborted!");
});
// Pipe the video stream.
const videoFile = Bun.file("./data/worker/video.mp4");
console.log("Streaming video file...");
await stream.pipe(videoFile.stream());
// Pipe the audio stream
// const audioFile = Bun.file("./data/worker/audio.mp4");
// console.log("Streaming audio file...");
// await stream.pipe(audioFile.stream());
console.log("Done!");
});
});
console.log("Worker is running on port 3001");
export default {
port: 3001,
fetch: app.fetch,
};
And consuming it from another app
app.get("/", async (c) => {
console.log("Streaming files from worker...");
const response = await fetch("http://localhost:3001/");
if (!response.ok) {
return c.json({ error: "Failed to stream files from worker" }, 500);
}
await Bun.write("./data/output/video.mp4", response.body);
return c.json({ message: "File streamed successfully" });
});
Now, how do I add a second file to the stream? The consumer will need to read both files and write them to the filesystem.
Upvotes: 0
Views: 543
Reputation: 1
Streaming App
import { Hono } from "hono";
import { stream } from "hono/streaming";
const app = new Hono();
app.get("/", (c) => {
return stream(c, async (stream) => {
stream.onAbort(() => {
console.log("Aborted!");
});
// Pipe the first video file
const videoFile = Bun.file("./data/worker/video.mp4");
console.log("Streaming video file...");
await stream.pipe(videoFile.stream());
// Send a delimiter or an identifier to signal the end of the first file
await stream.write(new TextEncoder().encode("\n--file-boundary--\n"));
// Pipe the second audio file
const audioFile = Bun.file("./data/worker/audio.mp4");
console.log("Streaming audio file...");
await stream.pipe(audioFile.stream());
console.log("Done streaming both files!");
});
});
console.log("Worker is running on port 3001");
export default {
port: 3001,
fetch: app.fetch,
};
The other app
import { Hono } from "hono";
import { Bun } from "bun"; // Import Bun for filesystem handling if needed.
const app = new Hono();
app.get("/", async (c) => {
console.log("Streaming files from worker...");
const response = await fetch("http://localhost:3001/");
if (!response.ok) {
return c.json({ error: "Failed to stream files from worker" }, 500);
}
const reader = response.body.getReader();
const decoder = new TextDecoder();
let buffer = "";
let isVideo = true; // Start with the assumption that the first file is the video
while (true) {
const { done, value } = await reader.read();
if (done) break;
// Append the chunk to the buffer
buffer += decoder.decode(value, { stream: true });
// Check for file boundary
if (buffer.includes("--file-boundary--")) {
const [firstFilePart, secondFilePart] = buffer.split("--file-boundary--");
// Write the first file part to disk
const firstFile = new TextEncoder().encode(firstFilePart.trim());
await Bun.write(isVideo ? "./data/output/video.mp4" : "./data/output/audio.mp4", firstFile);
// Set up for the next file
buffer = secondFilePart;
isVideo = !isVideo;
}
}
// Write any remaining part to the second file
if (buffer) {
const finalFile = new TextEncoder().encode(buffer.trim());
await Bun.write(isVideo ? "./data/output/video.mp4" : "./data/output/audio.mp4", finalFile);
}
return c.json({ message: "Both files streamed successfully" });
});
export default app;
Upvotes: -1