Я пытаюсь поместить некоторые аудиофайлы AIFF за стеной входа в систему на сайте PHP (то есть вне веб-корня). Первая проблема заключается в том, что AIFF поддерживаются не во всех браузерах, но это ожидается. http://www.jplayer.org/HTML5.Audio.Support/ Сейчас я использую Safari для тестирования, потому что он поддерживает AIFF.
Я не могу понять, почему Safari по-разному относится к двум версиям одного и того же файла. Для прямого файла он запускает плеер и работает. Для потокового файла проигрыватель не работает.
Обычная загрузка
Вот как выглядят заголовки, когда я загружаю файл напрямую (т.е. если я временно помещаю файл в корневой веб-каталог для тестирования):
curl -v http://audio.app/Morse.aiff -o /dev/null
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Trying 192.168.10.10...
* Connected to audio.app (192.168.10.10) port 80 (#0)
> GET /Morse.aiff HTTP/1.1
> Host: audio.app
> User-Agent: curl/7.49.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: nginx/1.8.0
< Date: Sun, 06 Nov 2016 03:19:03 GMT
< Content-Type: application/octet-stream
< Content-Length: 55530
< Last-Modified: Sat, 05 Nov 2016 21:51:02 GMT
< Connection: keep-alive
< ETag: "581e5446-d8ea"< Accept-Ranges: bytes
<
{ [5537 bytes data]
100 55530 100 55530 0 0 8991k 0 --:--:-- --:--:-- --:--:-- 10.5M
* Connection #0 to host audio.app left intact
Через PHP
И вот заголовки при потоковой передаче файла через мой PHP-скрипт (с именем source.php):
curl -v http://audio.app/source.php?file=Morse.aiff -o /dev/null
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Trying 192.168.10.10...
* Connected to audio.app (192.168.10.10) port 80 (#0)
> GET /source.php?file=Morse.aiff HTTP/1.1
> Host: audio.app
> User-Agent: curl/7.49.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: nginx/1.8.0
< Date: Sun, 06 Nov 2016 03:36:46 GMT
< Content-Type: application/octet-stream
< Content-Length: 55530
< Connection: keep-alive
< Last-Modified: Sat, 05 Nov 2016 21:51:02 GMT
< ETag: "581e5446T-d8eaO"< Accept-Ranges: bytes
<
{ [8431 bytes data]
100 55530 100 55530 0 0 4915k 0 --:--:-- --:--:-- --:--:-- 5422k
* Connection #0 to host audio.app left intact
Заголовки почти идентичны — единственное различие, которое я могу разглядеть, это их порядок и алгоритм хеширования, который использует мой локальный dev-блок для значения ETag.
Вот тестовый скрипт PHP (с именем source.php), который я использую для потоковой передачи того же файла (находится над webroot):
// Adapted from http://php.net/manual/en/function.readfile.php
$filename = (isset($_GET['file'])) ? $_GET['file'] : null;
// <do sanitization here>
$file = dirname(dirname(__FILE__)).'/audio/' . $filename;
// Mimicking AIFF headers from curl headers (does not work!)
$content_length = filesize($file);
$last_modified = date("D, d M Y H:i:s", filemtime($filename)). ' GMT';
header("HTTP/1.1 200 OK");
header("Content-type: application/octet-stream");
header('Content-Length: ' . $content_length);
header('Last-Modified: ' .$last_modified);
// attempts to do the same thing as NGINX... md5_file() would probably work
$etag = sprintf("\"%xT-%xO\"", filemtime($filename), $content_length);
header("ETag: $etag"); // quoting it exactly
header("Accept-Ranges: bytes");
// Output the file
readfile($file);
Ожидаемое поведение — браузер будет обрабатывать обе версии одинаково. В моем примере HTML-страницы (адаптировано из http://www.w3schools.com/html/html5_audio.asp), работает только прямая загрузка — версия файла, идущая через PHP, не воспроизводится. То же самое происходит, когда я открываю оба файла в браузере напрямую.
<!DOCTYPE html>
<html>
<body>
<h2>From Stream</h2>
<audio controls>
<source src="/source.php?file=Morse.aiff&breakcache=<?php print uniqid(); ?>" type="audio/x-aiff">
Your browser does not support the audio element.
</audio>
<hr/>
<h2>Direct Downloads</h2>
<audio controls>
<source src="/Morse.aiff" type="audio/x-aiff">
Your browser does not support the audio element.
</audio>
</body>
</html>
Тот же подход работал для воспроизведения mp3-файлов (но заголовки немного отличаются). Кто-нибудь знает, что я делаю не так, или кто-то знает, почему этот подход не работает с AIFF? Я еще не пробовал этот же тест с использованием другого серверного языка, но я подозреваю, что это не проблема PHP и есть что-то, что нужно сделать в AIFF. Кто-нибудь может пролить свет на это?
Задача ещё не решена.
Других решений пока нет …