h3
h3 copied to clipboard
Streaming video in Safari
Up to now I can stream files and videos with the following route logic in a /api/media/[id].get.ts:
import fs from 'fs'
import { sendStream } from 'h3'
import { getFilepathFromId } from '~~/server/lib/fileStorage'
export default defineEventHandler(async (event) => {
const fileId = event.context.params.id // id is always matching an existing file
const filepath = getFilepathFromId(fileId)
return sendStream(event, fs.createReadStream(filepath))
})
Images and Videos are streamed correctly on Chrome and Firefox but videos can not be played on Safari Browser. After a couple of requests, Safari returns network errors and the video can never be played.
Does anyone has tested it with h3 ?
Ok I have found. It is basically an HTTP standard. It seems Chrome and Firefox are handling this stream too well. We need to specify the file length for Safari:
import fs from 'fs'
import fs from 'fs'
import { sendStream } from 'h3'
import { getFilepathFromId } from '~~/server/lib/fileStorage'
export default defineEventHandler(async (event) => {
const fileId = event.context.params.id // id is always matching an existing file
const filepath = getFilepathFromId(fileId)
setHeader(event, "Content-Length", fs.statSync(filepath).size) // fix: set file length in HTTP header
return sendStream(event, fs.createReadStream(filepath))
})
It would be useful to include examples of file streaming in the documentation though. I post it as note for myself :)
@Lyokolux I have a base64 string (of an image) stored in a database. I am in desperate need of an example of how to return a response so that a route like /api/read-image shows the image, rather than a text response. Tried adapting the above code, but it didn't work. Any advice would be greatly appreciated.
Hi. In next version of h3 (1.8) you can directly return a web or node.js stream 👍🏼