I have searched and exhausted every solution I could find on stack overflow but with no joy.
Basically, I have a folder of images/videos. .htaccess redirects all requests to a .php file that checks a user can view these videos against a paywall, or redirects them to login. If the user is authorised then it sends the file. This works perctly for images and small videos.
However, once the video gets up to 500mb - 1GB I start getting: "The media could not be loaded, either because the server or network failed or because the format is not supported." On playing said video. Wierder still this seems only to be on safari or chrome.
Firefox plays these videos without any issue what so ever.
Here is my code to output the video:
$mime = mime_content_type($_SERVER['DOCUMENT_ROOT'].'/uploadvideos/'.$video);
ob_clean();
ob_flush();
flush();
header('Expires: 0');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: pre-check=0, post-check=0, max-age=0');
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Length: ".filesize(trim($_SERVER['DOCUMENT_ROOT'].'/uploadvideos/'.$video)));
// Force the download
header("Content-Type: ".$mime);
header('Content-Length: '.filesize($_SERVER['DOCUMENT_ROOT'].'/uploadvideos/'.$video));
readfile($_SERVER['DOCUMENT_ROOT'].'/uploadvideos/'.$video);
Can anyone see any headers that might be missing that I need to add or something to get this working properly, as it is literally driving me insane and I just cant fathom out what the cause is here.
I have added numerous header options but to no joy. I tried this one that some seemed to think from other Stackoverflow posts:
header("Content-Transfer-Encoding: binary");
$size = filesize(trim($_SERVER['DOCUMENT_ROOT'].'/uploadvideos/'.$video));
$begin = 0;
$end = $size - 1;
header("Content-Range: bytes $begin-$end/$size");
But this seemed to make the situation worse, and removing it made it at least work in Firefox.
Related
I am using soundmanager2 and I have a problem with Safari.
I am successfully streaming protected files (outside the webroot) from PHP to Soundmanager2, using something like this :
//check if user is logged in and has rights on $file
//if yes stream file
if (file_exists($file)) {
$filepath = $file;
$filesize = filesize($filepath);
header("Pragma: no-cache");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header('Content-Disposition: attachment;filename="'.$filename.'"');
header("Content-Transfer-Encoding: binary");
header('Content-Type: audio/mpeg');
header('Content-Length: '.$filesize);
#readfile($filepath);
exit(0);
}
This works fine on Firefox and Chrome, the mp3 files are playing, but in Safari I get :
soundmanager2.js:1190basicMP3Sound0: Using HTML5
soundmanager2.js:1190basicMP3Sound0: play(): Attempting to load
soundmanager2.js:1190basicMP3Sound0: load (/privateaccess/index/1415)
soundmanager2.js:1190basicMP3Sound0: waiting
soundmanager2.js:1190basicMP3Sound0: loadstart
soundmanager2.js:1190basicMP3Sound0: loadedmetadata
soundmanager2.js:1190basicMP3Sound0: HTML5 error, code 3
soundmanager2.js:1188basicMP3Sound0: Failed to load / invalid sound? Zero-length duration reported. (/privateaccess/index/1415)
I only get this error when I stream a file from PHP, it's working with files that are in the webroot (delivered by apache instead of PHP).
If I hit www.myurl.com/privateaccess/index/1415 directly, the file is downloaded, so it really seems like an issue between Safari,Soundmanager2 and PHP file streaming.
Anyone? an idea to fix/workaround this?
You need to support byte range requests. See SoundManager2's Technical Notes on the subject.
Example Request:
GET some.ogg HTTP/1.1
Range: bytes=5210604-5275910
Expected Response:
HTTP/1.1 206 Partial Content
Accept-Ranges: bytes
Content-length: 65307
Content-Range: bytes 5210604-5275910/5275911
Content-Type: audio/ogg
My question is simply: how can I output an mp3 with PHP that is seekable? I believe I have the appropriate headers set and I have tried with both readfile() and fopen() because my research has led me to believe that readfile() does not support byteranges and fopen() does. However, I really don't understand how to work with or set byteranges, just that I apparently need to. I am playing the song through jPlayer and the song plays fine, but it not seekable. In other words, you can't skip through the song by clicking different places on the seek bar.
Here is the code that is outputting the mp3 file:
header("Pragma: public"); // required
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private", false); // required for certain browsers
header("Content-Type: audio/mpeg, audio/x-mpeg, audio/x-mpeg-3, audio/mpeg3");
header("Content-Disposition: inline; filename=" . $file . ";" );
header("Content-Transfer-Encoding: binary");
header("Content-Length: " . filesize($path));
//readfile("$path");
$music = fopen($path, 'r');
fseek($music, 0);
fpassthru($music);
exit();
If I need to read the Range header, how do I do that?
I've spent days trying to solve the same thing. I'm yet to crack it, but I have noticed this.
Mp3s aren't skipping ahead (due to quicktime grabbing the first byte then going back to the rest)
soundcloud streams (which are mp3) however, are letting me skip ahead (when played through the same player)
I suspect you might find the solution in the the soundcloud headers (since they somehow cracked it).
I am using Zend and have some files outside of the webroot that I would like to be able to serve up. I have tried two approaches, both of which work in all browsers except for versions of IE 8 or lower.
The two (working) approaches that I have tried are the following:
// Approach #1
header('Content-Type: application/pdf');
header("Pragma: ");
header("Content-Disposition: attachment; filename=\"$filename\"");
//header('Content-Transfer-Encoding: binary');
header("Pragma: no-cache");
header("Expires: 0");
readfile($file);
// Approach #2
$this->getResponse()
->setHeader('Content-Disposition', "attachment; filename=$filename")
->setHeader('Content-type', 'application/x-pdf');
fpassthru($file);
Like I said, both approaches work in modern browsers (even IE9) but not in older versions of IE. The error I am getting is the following: http://cl.ly/image/1G3x370b1s09
I have looked into several posts on this topic and tried more different combinations of headers than I can even count. Is there a more bulletproof way of handling this functionality that wont cause issues with older browsers?
Thanks!
I've fought with this before and I think it stems from caching headers.
There's three: Expires, Cache-Control (HTTP 1.1), and Pragma (HTTP 1.0). My experience has been the older versions of IE like to see all three of these headers. Try using the following prior to any other headers and content you send:
header("Cache-control: no-cache");
header("Pragma: no-cache");
header("Expires: -1");
This article from Microsoft goes in to more discussion about the caching headers.
This is what I have done in the past to get it to work:
$file = $fileInfo->openFile('r');
header("Pragma: public");
header("Cache-Control: public");
header('Content-type: application/pdf');
header('Content-Disposition: attachment; filename="'.$file->getFilename().'"');
print $file->fpassthru()
Against my will I gave up on trying to fight with headers and completely changed the way I am handling file downloads. When a user requests a file now, it is temporarily hashed, copied to an area that the web-server can see, the user is redirect to that file and once they leave the download area the file is deleted. If they go inactive the file is deleted automatically at a set interval.
Thank you for all of the input kulishch and how ironic is it that you are from Minnesota as well!? Happy Holidays!
-- Nicholas
Follwing the advice at http://support.microsoft.com/default.aspx?scid=KB;EN-US;q316431&, these headers worked for me:
header("Cache-control: max-age=3600, must-revalidate");
header("Pragma: public");
header("Expires: -1");
I always get caught out by this! :(
I wrote a download script in PHP as specified below, my script is downloading the files correctly, but I am feeling that the browser(chrome) progress bar is not getting updated properly in regular intervals.
My file is of size 320MB, while downloading that file the progress is getting updated randomly as "11MB, 76MB, 200Mb & 320MB" or "70MB & 320MB" etc.
In most of the sites download progress update is happening in constant chunks like after every MB, so I want to know how we can control the progress update intervals, may be by sending some extra headers or something else.
I want to improve the user experience by updating the progress in constant intervals, so anybody please help me to handle this situation in a proper way.
// HTTP Headers for ZIP File Downloads
// http://perishablepress.com/press/2010/11/17/http-headers-file-downloads/
// file variables
$filename = "Movie Tunes.zip";
$filepath = "files/";
// http headers for zip downloads
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: public,must-revalidate, post-check=0, pre-check=0");
header("Content-Description: File Transfer"); // MIME
header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"".$filename."\"");
header("Content-Transfer-Encoding: binary"); // MIME
header("Content-Length: ".filesize($filepath.$filename));
ob_end_flush();
#readfile($filepath.$filename);
Thanks,
Siva
No, you cannot influence when/how the browser updates its download progress bar.
I'm offering a sermon downloading site and I have a user experiencing an issue with his download. Anyone have any ideas on how I can improve this code, or perhaps send better headers...
$path = "http://www.domain.com/sermon_files/".date("Y", $array["preached"])."/".$array["filename"];
$corePath = "/home/user/public_html/sermon_files/".date("Y", $array["preached"])."/".$array["filename"];
if (!file_exists($corePath)) {
echo "An error has occured with this download.";
} else {
header("Pragma: public"); // required
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private", false);
header("Content-Type: audio/mp3");
header("Content-Disposition: attachment; filename=\"".$array["title"]."\";" );
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize($corePath));
readfile($path);
exit();
}
Take a look at this thread, I had similar problems: PHP: Force file download and IE, yet again. Also consider using Fiddler to capture the exact HTTP headers that are being sent to the client.
Combine your PHP ( ? ) code with a server with X-Send available, lighttpd has it so does apache
Watch out for Expires: 0 on downloads. This messes with IE6's tiny little brain and makes it think there is no data to save/open. Try expiring in a minute from access and see if that fixes the problem. Otherwise, tell us exactly what the problem is.