I am not a web developer by all means. But I am trying to help someone deliver a video from their server. Basically when the user clicks a button on the website, we want the user to be prompted to download the video. So after Googling for a while I figured out how to write a short php script using content-disposition:
<?php
$fn = 'videoFile.mp4';
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private",false);
header('Content-Description: File Transfer');
header('Content-type: video/mp4');
header('Content-Length: '.filesize($fn));
header('Content-disposition: attachment; filename='.$fn);
readfile($fn);
?>
So the button on the website points to this script. PC browsers seem to start the download with no problem. But the main focus of this is for Android phones. When you click to download the file on the default Android Browser, it fails and all it says is "Download Unsuccessful".
Another thing is that on my computer (using Firefox), the download starts and at about 200MB, it just stops. It doesn't show any signs of failure, it just looks like it finished downloading. The actual file size is about 1GB.
I have played around with the content-type quite a bit, hoping that was the problem. I used "video/mpeg" and "application/force-download" and neither of them worked.
Is there something I'm not doing write? Could the 2 problems be related? Should I be going about this a different way? Thanks for any input.
The Android browser does not appear to like Content-disposition: and related headers. I recommend just a plain redirect to the file in question.
Related
I have a wrapper iOS app that uses WKWebView to display a web application.
For file downloads on the web app (written in PHP) we have a download link looking like this:
download.php?id=xyz
The download.php file then processes this and outputs the actual file in the headers:
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Content-Length: " . filesize($local_location));
header("Content-Type: " . $file_mime_type);
header("Last-Modified: $gmt_mtime");
header("Content-Disposition: inline; filename=\"".$name."\";");
header("Expires: 0");
set_time_limit(0);
readfile($local_location);
However, nothing happens in the WebView when the download link is clicked.
The session is authenticated, so we can't open the link in the default browser as there would be no authentication headers.
Ideally I'd like the file to save in a specified location (perhaps a popup where a user can select the location) - this is because the app will be compiled for iOS and MacOS.
Could anyone provide some guidance on this please?
The download method I am using:
I have a "Export" button in HTML which when clicked sends some data to the server.
The server processes the data, writes the CSV to a file and whether the writing was successful or not, sends an appropriate JSON message.
On receiving a success message, I do a window.open with the proper url and attached file name to start the download.
The download happens on Firefox in Ubuntu 15.04 alright as well as IE 11 on Windows 7.
However the download fails on Google Chrome 45.0.2454.85 m on Windows 7. It just opens a new blank window and then nothing happens. I have browser cache cleared. What is the right way to start a file download for Chrome?
Here is the PHP code responsible for the download.
header("Content-Description: File Transfer");
header("Content-Type: text/csv");
header("Content-Disposition: attachment; filename=". basename($filename));
header("Expires: 0");
header("Cache-Control: must-revalidate");
header("Pragma: public");
header("Content-Length: ". filesize($filename));
ob_clean();
flush();
readFile($filename);
Try write all your headers after ob_clean().
ob_clean() clear all data with headers.
I have used following code to download approximate 920MB file,
set_time_limit(0);
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("X-Sendfile: $zipname"); // For Large Files
header("Content-type: application/zip");
header("Content-Disposition: attachment; filename=\"".$zipname."\"");
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize($directory_location . '/' . $zipname));
ob_end_flush();
readfile($directory_location . '/' . $zipname);
Before this code i did some study with the following links Using X-Sendfile with Apache/PHP, Streaming a large file using PHP and Limit download speed using PHP but not much helpful to me because file download still takes more time with just (2MB) file. It's not showing and transfer rate or anything else. I want download start to serve file with around 60Kbps, with all files (Large or small)
UPDATE: One more thing i noticed its not showing any download process just executing and after sometime display the pop-up to choose the location, and after hitting save button its direct save to the computer without any downloading process window :(
Please help me to guide the right way.
Based on above comments there are two solutions:
1) Just download the file directly. You don't appear to be doing any validation, so if not, then just pass the user to the file to download and let apache handle it.
2) If you do need validation / pre-processing, then check mod_xsendfile - adding the header isn't enough, you actually need to add the mod to apache. If you're in Linux then compile from source (https://tn123.org/mod_xsendfile/). If you're not in Linux then mod_xsendfile for Win x64? has a response from the author saying he can provide binaries - but that's in 2010. There's a bit of advice around the web - although it's been a while since I looked at it so can't really help much more.
I have a link to download mp3 on all mobile device they can read them.
I also have an Acer E320 with Android 2.3.4 and I want to download my mp3 by clicking my link (web server Apache; this is some PHP source behind that link).
I tried with a BlackBerry, and I got the file.
I tried with my Firefox browser with a user-agent of a Samsung Galaxy S with Android, and I got the file.
I tried with my Acer E320 with the same Android 2.3.4, and... I didn't get the file.
I am obviously sure that comes from the OS, I'll try with a Windows Phone tomorrow but I'm pretty sure this will works.
Here are my sources for the download:
<?php
// assume that all variables are correctly set
header("Pragma: public");
header("Expires: 0");
header("Cache-Control:");
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Type: audio/mpeg");
header('Content-Disposition: attachment; filename="'.$filename.'";');
header("Content-Transfer-Encoding: binary");
header('Content-Range: ' . $download_range);
header('Content-Length: ' . $download_size);
readfile($filename);
?>
Thank you if you have any idea why this code doesn't work on an Android phone.
EDIT: I tried with an HTC with Windows Phone OS. The download didn't start but I can see my hit on the apache log... It seemes that Android is not alone...
2nd EDIT: I finnaly find it: there's a pre-fetch done with Android that kill my download because of a one-use token.
Thanks all
I finally found it:
There's a pre-fetch done with Android that kills my download, because of a one-use token.
Thanks all.
I have just moved a web application to a windows server and having some problems. One of it is -
application stores list of names of files in a database table. when a files is requested for download it is sent to output by sending proper headers (depending upon mime type and then a readfile("document location/filename.extension");
it works fine in firefox but if I try to download in IE it throws
IE can not dowload this document from
www.mysite.com .. IE was unable to
open this Internet site. The requested
file is either unavailable or cannot
be found. Please try again later.
As it was working fine on previous server (non-windows), I tried to print document location and it read somewhat like C:/Apache/htdocs/FILENAME.ext and I guess this C:/ is causing problem in IE but not in firefox??
How do I get it working right in IE??
Thanks
UPDATE
I have got it working by
adding some more headers among others .. I think first 2 are more important for IE or so (atleast working for me for now :)
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
It works :
if (strstr($_HTTP_USER_AGENT, "MSIE")) {
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: doit-revalider, post-check = 0, pré-check = 0");
header("Content-Type: application de téléchargement; name=\"$sFilename\"");
header("Content-Length: $iTaille");
header("Content-Disposition: attachment; filename=\"$sFilename\"");
header("Content-Transfer-Encoding: binary");
} else {
header("Content-Type: application de téléchargement; name=\"$sFilename\"");
header("Content-Length: $iTaille");
header("Content-Disposition: attachment; filename=\"$sFilename\"");
}
this question had already been answered here PHP: Force file download and IE, yet again
Is this by any chance over SSL? If so, there are a whole host of bugs in MSIE which could be affecting your app. Try setting a very short caching time.
If it works on Firefox using the the same server, then the problem unlikely to be anything to do with the path on the server. Although beware that (IME) IIS seems to tunnel authorization from MSIE clients (but not others) in some instances.