Как подать аудиофайл для потоковой передачи из Grails с кодом 206?

Я пытаюсь передать аудио/wav с помощью функции HTML5 следующим образом:

<audio type="audio/wav" src="/sound/10/audio/full" sound-id="10" version="full" controls="">
</audio>

Это хорошо работает в Chrome, за исключением того факта, что невозможно воспроизвести или изменить положение атрибута currentTime:

var audioElement = $('audio').get(0)
audioElement.currentTime
> 1.2479820251464844
audioElement.currentTime = 0
audioElement.currentTime
> 1.2479820251464844

Я передаю аудиофайл с контроллера Grails, используя следующий код:

 def audio() {
    File file = soundService.getAudio(...)
    response.setContentType('audio/wav')
    response.setContentLength (file.bytes.length)
    response.setHeader("Content-disposition", "attachment;filename=${file.getName()}")
    response.outputStream << file.newInputStream() // Performing a binary stream copy
    response.status = 206

    return false
}

Похоже, что Grails возвращает HTTP-ответ 200 вместо 206 (Partial-Content), как видно из следующего вывода Chrome:

Request URL:http://localhost:8080/sound/10/audio/full
Request Method:GET
Status Code:200 OK
Request Headersview source
Accept:*/*
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:identity;q=1, *;q=0
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Cookie:JSESSIONID=9395D8FFF34B7455F937190F521AA1BC
Host:localhost:8080
Range:bytes=0-3189
Referer:http://localhost:8080/cms/sound/10/edit
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.11 (KHTML, like Gecko)                 Chrome/23.0.1271.97 Safari/537.11
Response Headersview source
Content-disposition:attachment;filename=full.wav
Content-Length:3190
Content-Type:audio/wav
Date:Wed, 19 Dec 2012 13:58:44 GMT
Server:Apache-Coyote/1.1

Есть идеи, что может быть не так?

Спасибо, Амит.

ДОБАВЛЕНИЕ:

Изменение логики контроллера на:

response.status = 206
response.setContentType(version.mime)
response.setContentLength (file.bytes.length)
response.setHeader("Content-disposition", "attachment;filename=${file.getName()}")
response.outputStream << file.newInputStream() // Performing a binary stream copy

Помог с возвратом HTTP-206 (Partial-Content), однако и Chrome, и Firefox не будут воспроизводить аудиофайл (еще раз упоминая, что Chrome воспроизводил, когда он получил файл с 200...)

Снимок экрана сетевой консоли Chrome

со следующей информацией об ответе:

 Request URL:http://localhost:8080/sound/10/audio/full
 Request Headersview source
 Accept-Encoding:identity;q=1, *;q=0
 Range:bytes=0-
 Referer:http://localhost:8080/cms/sound/10/edit
 User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.97 Safari/537.11

person amit    schedule 19.12.2012    source источник
comment
Может быть, установить response.status = 206 перед потоковой передачей файла?   -  person Matthijs Bierman    schedule 19.12.2012
comment
Это определенно помогло получить код 206 (сброс заголовков с помощью curl). Но тогда проигрыватель «аудио» серый и не отвечает. Редактирование моего вопроса с дополнительной информацией.   -  person amit    schedule 19.12.2012


Ответы (1)


Вы можете попробовать:

response.reset();
response.setStatus(206);
response.setHeader("Accept-Ranges", "bytes");
response.setHeader("Content-length", Integer.toString(length + 1));
response.setHeader("Content-range", "bytes " + start.toString() + "-" + end.toString() + "/" + Long.toString(f.size()));
response.setContentType(...);

И этот тип вывода следует делать только в том случае, если клиент специально запросил диапазон. Вы можете проверить, используя:

String range = request.getHeader("range");

если диапазон не равен нулю, вам придется проанализировать диапазон для запросов начального и конечного байтов. Обратите внимание, что вы можете использовать «0-» в качестве диапазона. В некоторых случаях вы увидите «0-1» в качестве запроса, чтобы узнать, знает ли ваша служба, как обрабатывать запросы диапазона.

person Tommy Hui    schedule 22.12.2012