我使用Play框架成功提供视频,但我遇到了一个问题:每次提供文件时,Play框架都会在C:\ Users \ user \ AppData \ Temp中创建一个副本。我正在提供大型文件,因此很快就会产生磁盘空间问题。
有没有办法在Play中提供文件而不创建副本?或者让Play自动删除临时文件?
我用来服务的代码基本上是:
public Result video() {
return ok(new File("whatever"));
}
答案 0 :(得分:1)
使用流媒体
我使用以下方法进行视频流传输。此代码不会创建媒体文件的临时副本。
此代码基本上响应浏览器发送的RANGE
查询。如果浏览器不支持RANGE
查询,我会回退到我尝试使用Ok.sendFile
发送整个文件的方法(内部播放也会尝试流式传输文件)(这可能会创建临时文件)。但是,当浏览器不支持范围查询时,这种情况很少发生。
GET /media controllers.MediaController.media
将此代码放在名为Controller
MediaController
中
def media = Action { req =>
val file = new File("/Users/something/Downloads/somefile.mp4")
val rangeHeaderOpt = req.headers.get(RANGE)
rangeHeaderOpt.map { range =>
val strs = range.substring("bytes=".length).split("-")
if (strs.length == 1) {
val start = strs.head.toLong
val length = file.length() - 1L
partialContentHelper(file, start, length)
} else {
val start = strs.head.toLong
val length = strs.tail.head.toLong
partialContentHelper(file, start, length)
}
}.getOrElse {
Ok.sendFile(file)
}
}
def partialContentHelper(file: File, start: Long, length: Long) = {
val fis = new FileInputStream(file)
fis.skip(start)
val byteStringEnumerator = Enumerator.fromStream(fis).&>(Enumeratee.map(ByteString.fromArray(_)))
val mediaSource = Source.fromPublisher(Streams.enumeratorToPublisher(byteStringEnumerator))
PartialContent.sendEntity(HttpEntity.Streamed(mediaSource, None, None)).withHeaders(
CONTENT_TYPE -> MimeTypes.forExtension("mp4").get,
CONTENT_LENGTH -> ((length - start) + 1).toString,
CONTENT_RANGE -> s"bytes $start-$length/${file.length()}",
ACCEPT_RANGES -> "bytes",
CONNECTION -> "keep-alive"
)
}