I want use html5's new tag to play a wav file (currently only supported in FF.)
https://developer.mozilla.org/En/HTML/Element/Audio
I"m using php's readfile command to get the wav file off the hdd, and write it to the http response.
But its not working. The audio widget in firefox just has the loading animation running constantly.
The tag seems to be fine as I can put a different url in it's src/source and it works fine. I can use an tag and that downloads the file and it plays using Quicktime fine.
So I thinking perhaps its one/all of the content headers.
Using the FF Extension httpfox I can see these response headers arrive from the server:
(Status-Line) HTTP/1.1 200 OK
Date Mon, 12 Oct 2009 03:04:33 GMT
Server securesauce
Cache-Control private
Expires Mon, 26 Jul 1997 05:00:00 GMT
Pragma private
Vary Accept-Encoding
Content-Encoding gzip
Content-Length 8217
Keep-Alive timeout=15, max=100
Connection Keep-Alive
Content-Type audio/x-wav
So everything looks how I'd expect it to. The only headers I'm explicitly setting in the script (others are set elsewhere in the app) are:
Cache-Control private
Pragma private
Content-Type audio/x-wav
When I tried a different wav file (random one off the internet) httpfox didn't list any response headers.
Because its a php file sending out the content, I can't just send no headers, as I'd have to at least send the content-type.
Any ideas?
Source excerpt:
header('Cache-Control: private');
header('Pragma: private');
header("Content-Type: $contentType");
readfile($filepath);
exit;
Which formats and MIME types are supported by Mozilla is documented on their wiki. It doesn't look like the MIME type is your problem, but it's quite possible that this WAVE file isn't using the plain PCM audio which Firefox supports. WAVE can actually contain other formats like ADPCM, MP3 and whatnot. These may be supported by QuickTime, but there's no guarantee that it will play in a HTML5 browser. To be sure, try opening the file in a audio editor and saving it again as a WAVE PCM file.
You're missing X-Content-Duration. It's needed for the client to seek accurately during playback, and some clients refuse media content unless the duration is included. Also include Content-Duration, which is slowly replacing X-Content-Duration.
Here is some more information: Configuring web servers for HTML5 Ogg video and audio
Also, I would avoid using gzip or encryption on your output.
Have you tried the url of the audio file directly in your browser? If it contains an error or a warning that will make your header obsolete. and also try to open the audio file from the browser, see if it is correct.
I had the same trouble sending an ogg audio file using php. Playing with the headers did not help.
Then I updated from firefox 3.5.2 to 3.5.4 - that fixed the problem.
Related
I am working with scanning images.
Today I made a step forward but I think that I need something more in the header maybe?
Currently a scan request is POSTed to app running on Apache server and PHP 7.0. I receive that post and today I figured out I needed to reply with a custom 201 header.
I have the following custom headers set in PHP
header('HTTP/1.1 201', Created);
header('Location: /eSCL/Scans');
header('Cache-Control: no-cache, no-store, must-revalidate');
After doing I was able to see that a request is now made for an image, from the app to Apache server to /eSCL/Scans/NextDocument. "NextDocument" is actually a softlink to a .jpg, (but may also later be a PDF). The app GETs this file, I can also see that the server replies with the JPG file . That image should display in the scan app that made the request, but never does.
I think however I need something in the header to tell it it is a JPG , especially given it loads from a softlink with no extension . I tried the following with the same result
header('HTTP/1.1 201', Created);
header('Content-type:image/jpeg');
header('Location: /eSCL/Scans');
header('Cache-Control: no-cache, no-store, must-revalidate');
There must be a magic soup that causes the image to display in the app.I have tried both VueScan and Mopria android app with the same results
Thanks for any ideas in advance
I'm using the TrueVault REST API to upload/download Blobs per the documentation at https://docs.truevault.com/Files
To download an existing Blob, I'm passing the Blob URL directly to the client's web browser (Firefox) via a PHP Header redirect. The client is able to download the Blob content from TrueVault without issue, but when using Firefox I've noticed that if the Blob being downloaded has spaces in the filename, the filename is truncated when downloading.
For instance, if I upload a Blob to TrueVault with filename 'Test File.txt', it gets downloaded to Firefox as just 'Test'. I've seen this behavior in other PHP apps and the fix has been to put quotes around the filename in the Response Headers, as seen here.
I've traced the Response Headers from TrueVault when downloading and I can see where the filename is being passed to the client without any quotes around the name. Since the client is downloading the Blob directly from TrueVault, there's nothing I can do in my code to affect this behavior. Anyone else seeing this behavior? Any suggestions?
Strict-Transport-Security: max-age=31536000
Server: gunicorn/18.0
Date: Wed, 29 Apr 2015 14:40:28 GMT
Content-Type: application/zip
Content-Length: 11377
Content-Disposition: attachment; filename=Test file with Spaces.docx
Connection: keep-alive
Cache-Control: no-cache
This issue will be addressed by 4/30/2015. Thanks for bringing this to our attention.
I am looking for a way to confirm if X-Sendfile is properly handling requests handed back to the webserver by a script (PHP). Images are being served correctly but I thought I would see the header in curl requests.
$ curl -I http://blog2.stageserver.net/wp-includes/ms-files.php?file=/2011/05/amos-lee-feature.jpg
HTTP/1.1 200 OK
Date: Wed, 04 Jan 2012 17:19:45 GMT
Server: Cherokee/1.2.100 (Arch Linux)
ETag: "4dd2e306=9da0"
Last-Modified: Tue, 17 May 2011 21:05:10 GMT
Content-Type: image/jpeg
Content-Length: 40352
X-Powered-By: PHP/5.3.8
Content-Disposition: inline; filename="amos-lee-feature.jpg"
Configuration
Cherokee 1.2.100 with PHP-FPM 5.3.8 in FastCGI:
cherokee.conf: vserver!20!rule!500!handler!xsendfile = 1
(Set by vServer > Behavior > Extensions php > Handler: Allow X-Sendfile [check Enabled])
Wordpress Network / WPMU 3.3.1:
define('WPMU_SENDFILE',true); is set in the wp-config.php the following just before wp-settings.php is included. This will trigger the following code to be executed in WP's wp-includes/ms-files.php:50 serves up files for a particular blog:
header( 'X-Sendfile: ' . $file );
exit;
I have confirmed that the above snippet is executing by adding an additional header for disposition right before the exit(); call. That Content-Disposition is present with curl results above and not originally in the ms-files.php code. The code that was added is:
header('Content-Disposition: inline; filename="'.basename($file).'"');
Research
I have:
Rebooted php-fpm / cherokee daemons after making configuration changes.
Tried several tricks in the comments over at php.net/readfile and replaced the simple header in ms-files.php with more complete code from examples.
php.net/manual/en/function.readfile.php
www.jasny.net/articles/how-i-php-x-sendfile/
*codeutopia.net/blog/2009/03/06/sending-files-better-apache-mod_xsendfile-and-php/*
Confirmed [cherokee support][5] and tested [with and without][6] compression even though I don't think it would apply since my images are serving correctly. I also found a suspiciously similar problem from a lighttpd post.
*cherokee-project.com/doc/other_goodies.html*
code.google.com/p/cherokee/issues/detail?id=1228
webdevrefinery.com/forums/topic/4761-x-sendfile/
Found a blurb here on SO that may indicate the header gets stripped
stackoverflow.com/questions/7296642/django-understanding-x-sendfile
Tested that the headers above are consistent from curl, wget, Firefox, Chrome, and web-sniffer.net.
Found out that I can't post more than 2 links yet due to lack of reputation.
Questions
Will X-Sendfile be present in the headers when it is working correctly or is it stripped out?
Can the access logs be used to determine if X-Sendfile is working?
I am looking for general troubleshooting tips or information here, not necessarily specific to PHP / Cherokee.
Update
I have found a suitable way to confirm X-Sendfile or X-Accel-Redirect in a test or sandbox environment: Disable X-Sendfile and check the headers.
With Allow X-Sendfile disabled in Cherokee:
$ curl -I http://blog2.stageserver.net/wp-includes/ms-files.php?file=/2011/05/amos-lee-feature.jpg
HTTP/1.1 200 OK
Date: Fri, 06 Jan 2012 15:34:49 GMT
Server: Cherokee/1.2.101 (Ubuntu)
X-Powered-By: PHP/5.3.6-13ubuntu3.3
Content-Type: image/jpeg
X-Sendfile: /srv/http/wordpress/wp-content/blogs.dir/2/files/2011/05/amos-lee-feature.jpg
Content-Length: 40352
The image will not load in browsers but you can see that the header is present. After re-enabling Allow X-Sendfile the image loads and you can be confident that X-Sendfile is working.
According to the source on github X-Sendfile headers will be stripped.
If I'm skimming the file correctly, it's only logging success if it's been compiled in debug mode.
You could check memory usage of sending large files with and without xsendfile.
They are being stripped, simply because having them present will prevent one of the reasons to use it, namely having the file served without the recepient knowing the location of the file being served.
I have a PHP script that responds to a GET request for audio resources. An HTML5 Audio tag requests an audio file such as:
<audio src="get_audio.php?f=fun" preload></audio>
There is no need for the user to download that same audio file every time so I would like to cache it. In my PHP file I have:
header("Cache-Control: max-age=2419200");
header("Content-Type: audio/mpeg");
...
echo file_get_contents($path);
but when I view the Network tab of Chrome developer tools I see that it re-downloads the audio clip everytime rather than saying "from cache" and if I look in the Response headers I do see the Cache-Control header that I set. Why would it ignore this? Amidoingitright?
It's been a while since I did this in PHP, but try adding:
header("Pragma: public");
above the cache-control header.
I also think you need the expires header:
header('Expires: ' . gmdate('D, d M Y H:i:s', time()+2419200) . ' GMT');
Other than that you could start using the get_headers() function in PHP to debug where it's going wrong.
Do you see a header in the second request called If-Modified-Since:?
This is what you need to catch, parse and respond to - if you don't want to send the file again, you respond with HTTP/1.1 304 Not Modified. If you are using Apache, you can check for the header in the result of apache_request_headers(). If you are not using Apache, you may find it hard to handle this - you will probably have to find a way for the web server to set the headers as environment variables, so they are available in $_ENV or $_SERVER. There is a way to do this in Apache using mod_rewrite (see latest comment on page linked above), so there is probably a way to do it in other server environments as well.
Caching in HTTP 1.1 permits (and indeed, encourages) this behaviour - it means that the cached copy will always be up-to-date.
EDIT #2
Ok, the problem is different to what I originally thought, so I'm putting this 'edit' up the top. I've also updated the question title (the old one was 'Streaming wav audio from a mysql blob').
The problem now seems to be related to CodeIgniter sessions. The above script will only run if the user is logged in. For some reason, when I manually set the response headers (either
with php's header() or codeigniters output class) I can see from my logs that everything gets reloaded and reinitilised -- and that the session data is lost, so the user is no longer logged in, so the script is actually outputting an error.
Once I removed any requirement or reference to session data the audio plays fine... but this isn't really an option unless I can manage to authenticate the user some other way. Very frustrating.
.
.
.
** Original Text **
I have a mysql blob which contains audio data in wav format. I'm trying to output that to the browser to stream in whatever audio player plugin the browser wants to use.
The audio player works fine if I point it at a physical .wav file, so that doesn't seem to be a problem. However, if I point it at my PHP script I get a 'Search for suitable plugin?' popup in Firefox (which fails to find anything), and just an empty inactive player in Chrome.
Here's the PHP, the $aud object contains information retrieved from the database:
header("Content-length: $aud->size");
header("Content-type: audio/x-wav");
echo $aud->recording;
exit();
If I add header("Content-Disposition: attachment; filename=$name"); to the above I get to download the file, which then plays fine in an external audio player, but that's not what I want.
This snippit is part of a CodeIgniter application, if that would make a difference. I have routing set up so that /audio/$id.wav will grab the appropriate data and output it with the code above.
Can anyone see or think of any reason the above might not be working?
EDIT
These are the headers returned by the php script:
Date: Tue, 22 Mar 2011 22:12:06 GMT
Server: Apache/2.2.16 (Ubuntu)
X-Powered-By: PHP/5.3.3-1ubuntu9.3
Set-Cookie: ci_session=<long encrypted session string>; expires=Wed, 23-Mar-2011 00:12:06 GMT; path=/
Content-Length: 12345
Keep-Alive: timeout=15, max=98
Connection: Keep-Alive
Content-Type: audio/x-wav
200 OK
And for comparison, these headers are returned when I force a download of the above audio and open that wav file directly in the browser:
Date: Tue, 22 Mar 2011 22:10:53 GMT
Server: Apache/2.2.16 (Ubuntu)
Last-Modified: Tue, 22 Mar 2011 22:08:30 GMT
Etag: "200a83-3039-49f197bfcb380"
Accept-Ranges: bytes
Content-Length: 12345
Content-Type: audio/x-wav
200 OK
Saving and then opening the file directly does work. Having the PHP script output to the browser does not.
I would start investigating this problem by comparing the HTTP content-length, content-type, and all the other headers sent by the web server when pointing to the physical .wav file, with the headers sent when trying to open the PHP script. I think the actual content body is correct, according to your post stating that if you download the file as an attachment, it can be played with an audio player application.
Try adding this header in there:
header('Content-Transfer-Encoding: binary');
See if that helps it out.