html5 download and php download not working on mobile devices - php

On my site I have a <a download></a> link and also a php function that downloads files on my desktop just fine -
ob_start();
$nameOld = 'https://my-other-server.online/path/to/file.mp4';
$save = '/var/path/to/file.mp4';
$nameNew = "download.mp4";
file_put_contents($save, fopen($nameOld, 'r'));
set_time_limit(0);
header('Connection: Keep-Alive');
header('Content-Description: File Transfer');
header('Content-Type: application/force-download');
header("Content-Disposition: attachment; filename=$nameNew");
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($save));
while (ob_get_level()) {
ob_end_clean();
}
readfile($save);
exit;
unlink($save);
On mobile devices (iphone) this doesnt work on chrome browser. (Im already aware about safari ios downloads, even though I've seen some downloads prompt the user to open another app to continue.)
So I've tried using the <a></a> download link, but when clicking on it, it simply opens the video in a new tab and plays it.
If I try with a php script, it opens the video in a new tab and shows a crossed out play button (video is not even playable). I've been searching for an answer for days, I've edited .htaccess files and testing different scripts, content-types, headers, etc.
This is how the current script looks like for mobile specific -
... first few lines same as above script ...
file_put_contents($save, fopen($nameOld, 'r'));
//echo file_get_contents($save);
//$headers = get_headers($nameOld, 1);
//$filesize = $headers['Content-Length'];
//set_time_limit(0);
ob_clean();
//if(ini_get('zlib.output_compression'))
// ini_set('zlib.output_compression', 'Off');
//$fp = #fopen($save, 'rb');
//header('Connection: Keep-Alive');
//header('Content-Description: File Transfer');
//header('Content-Type: application/force-download');
//header('Content-Type: application/octet-stream');
header('Content-Type: video/mp4');
//header("Content-Disposition: attachment; filename=$nameNew");
header("Content-disposition: attachment; filename=\"" . basename($save) . "\"");
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
//header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($save));
//ob_end_clean();
while (ob_get_level()) {
ob_end_clean();
}
//fpassthru($fp);
// fclose($fp);
readfile($save);
//exit;
unlink($save);
die();
I also tried testing printing on mobile the headers of one of the files -
print_r(get_headers($url));
print_r(get_headers($url, 1));
The output today is as follows, but yesterday the content-type said application/octet-stream ---
Array ( [0] => HTTP/1.1 200 OK [1] => Date: Wed, 27 Feb 2019 14:51:56 GMT [2] => Server: Apache/2.4.29 (Ubuntu) [3] => Last-Modified: Tue, 26 Feb 2019 14:16:19 GMT [4] => ETag: "3e7e3a-582ccb37e75a7" [5] => Accept-Ranges: bytes [6] => Content-Length: 4095546 [7] => Connection: close [8] => Content-Type: video/mp4 ) Array ( [0] => HTTP/1.1 200 OK [Date] => Wed, 27 Feb 2019 14:51:56 GMT [Server] => Apache/2.4.29 (Ubuntu) [Last-Modified] => Tue, 26 Feb 2019 14:16:19 GMT [ETag] => "3e7e3a-582ccb37e75a7" [Accept-Ranges] => bytes [Content-Length] => 4095546 [Connection] => close [Content-Type] => video/mp4 )
I've also checked my php info settings and didnt see anything that could be causing an issue, but then again Im not too sure what to look for.
I know its possible to download files on chrome mobile because other sites work for me, just not my own.
What am I doing wrong?

Add this as a header : 'X-Content-Type-Options: nosniff';
it is made to prevent browsers from interpreting themself the received content.
In association wth Content-disposition: attachment; ... the browser should offer to download it.

Are you sure you are using the format:
<a href="myvideo.mp4" download>Download</a>
And as miken32 mentioned :
"You're setting the MIME type to video/mp4. If the browser can play that kind of video, it will do so. Change it back to application/octet-stream."
EDIT:
You could also try to set this in your .htaccess file:
AddType application/octet-stream .mp4
And then change it back to application/octet-stream.
Try this.

A while ago trying to make a small application and the download tag just worked for me in Chrome. Like this:
Download

Related

pdf file displays as text/html instead of application/pdf

I'm trying to display a .pdf file in a php application. It works perfectly well on my local development setup but on production, the same code displays the pdf as garbled text.
These are the request headers i'm using:
<?php
$file = $_GET["f"];
$filename = 'contrato.pdf';
header('Content-type: application/pdf');
header('Content-Disposition: inline; filename="' .$filename. '"');
header('Content-Transfer-Encoding: binary');
header('Accept-Ranges: bytes');
readfile($file);
?>
These are the production response headers according to chrome:
Connection:Keep-Alive
Content-Encoding:gzip
Content-Type:text/html
Date:Mon, 03 Apr 2017 21:31:19 GMT
Keep-Alive:timeout=15, max=189
Server:Apache
Transfer-Encoding:chunked
Vary:Accept-Encoding
On the development setup, the response headers are these:
Accept-Ranges:bytes
Connection:Keep-Alive
Content-Disposition:inline; filename="contrato.pdf"
Content-Transfer-Encoding:binary
Content-Type:application/pdf
Date:Mon, 03 Apr 2017 21:33:44 GMT
Keep-Alive:timeout=5, max=100
Server:Apache/2.4.7 (Win32) PHP/5.5.8
Transfer-Encoding:chunked
X-Powered-By:PHP/5.5.8
Could it be due to the apache settings?
I think it's the error in this line:
header('Content-type: application/pdf');
Note the small letter t
this line should be like this:
header('Content-Type: application/pdf');
also note that you are reading a file using the $_GET["f"]
this is wrong, instead read the file from $filename variable.
Change the last line to :
readfile($filename);
Anyway here's the correction of your code:
<?php
$file = $_GET["f"];
$filename = 'abc.pdf';
header('Content-Type: application/pdf');
header('Content-Disposition: inline; filename="' .$file. '"');
header('Content-Transfer-Encoding: binary');
header('Accept-Ranges: bytes');
readfile($filename);
?>

PHP readfile not working correctly with Safari

I am loading an mp3 into an html <audio> tag. The source of that tag is really a php script which returns a song that is not hosted in the public directory.
Omitting most of validation and other code, the headers used to output the mp3 are:
header( 'Content-type: {$mime_type}' );
header( 'Content-length: ' . filesize( $file ));
header( 'Content-Disposition: inline;filename="'.$filename.'"' );
header( 'Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0' );
header( 'Pragma: no-cache' );
header( 'Content-Transfer-Encoding: binary');
header( 'Expires: 0');
readfile( $file );
This works on Firefox, Chrome (and mobile), Edge (and mobile) and Opera. However I can't seem to get Safari to use the generated url as an audio source. In fact, no audio source appears in the DOM after the page has rendered:
The url might look like, www.website.com/song.php?sid=234234234234
I have tried tweaking this file plenty of times but can't see to figure out why this is happening on Safari. My intuition is the way the browser deals with mp3s and the like, which should be dealt with in the header.
Any guidance, hints or help would be appreciated.
Thanks.
update:
Added the network, shows that it loads the mp3 but then the second request doesn't?
response headers:
Name Value
Server Apache
Content-Type audio/mpeg, audio/x-mpeg, audio/x-mpeg-3, audio/mpeg3
Date Wed, 28 Dec 2016 17:24:48 GMT
Cache-Control no-cache
X-Powered-By PHP/5.3.29
Content-Disposition inline;filename="148_2793d1c49976a3689147634359577ec1aa5619f1.mp3"
Content-Length 834312
Expires 0
Connection Keep-Alive
Content-Transfer-Encoding binary
Accept-Ranges bytes
Keep-Alive timeout=5, max=100
Pragma no-cache
You need to pass the Multiple ranges header, because it's a partial content: http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.2
header("Accept-Ranges: 0-filesize( $file )");
EDIT
Take a look here:
http://www.techstruggles.com/mp3-streaming-for-apple-iphone-with-php-readfile-file_get_contents-fail/
You need to define some headers for safari, even for the mobile version.
I had this issue sometime ago, sorry if I don't remember correctly how I fixed that, but is a header issue (its the main part I can remember, and I don't use comments for adding the answer because its too long)
Try with this..
header( 'Accept-Ranges: bytes');
header("Pragma: public");
header("Expires: 0");
header('Cache-Control: no-cache, no-store');
header('Content-Transfer-Encoding: binary');
header('Content-Disposition: inline; filename="'.$filename.'"');
header('Content-Length: '.$fsize);
header('Content-Type: audio/'.$t);
header('Accept-Ranges: bytes');
header('Connection: Keep-Alive');
header('Content-Range: bytes 0-'.$shortlen.'/'.$fsize);
header('X-Pad: avoid browser bug');
header('Etag: '.$etag);
Where:
$filename = "myaudio.mp3";
$path = 'music/'.$filename;
$fsize = filesize($path);
$shortlen = $fsize - 1;
$fp = fopen($path, 'r');
$etag = md5(serialize(fstat($fp)));
fclose($fp);
$t = "mpeg";
Hope this helps, but the 2 main headers you need is "Etag" and "Accept-Ranges" if I'm not wrong.

download file with php

i want to create a link to download an excel file from the root in server computer, using php. so i wrote a simple code as below,
<?php
header("Content-disposition: attachment; filename=example.xls");
header("Content-type: application/vnd.ms-excel");
readfile("example.xls");
?>
it then can be downloaded however when i want to open it, i got the error saying the file i downloaded is in a different format than specified by the file extension. i also tried the same method with jpeg file and didnt get the same error but when i click it, it shows nothing. can someone help me? im not very good with programming. thank you in advance!
Try this
$file='example.xls'; $filesize=filesize($file);
header("Expires: Thu, 19 Nov 1981 08:52:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0");
header("Pragma: no-cache");
header('Content-type: application/vnd.ms-excel');
header('Content-Disposition: inline; filename="'.basename($file).'"');
header("Content-Length: " . $filesize);
$fh = fopen("$file, "rb");
// output file
while(!feof($fh))
{
# output file without bandwidth limiting
print(fread($fh, filesize($file)));
}
fclose($fh);

PHP forces PDF file download even though I'm using Content-Disposition: inline

I'm trying to display a PDF in the browser if possible--and I know I can do this in Chrome, which is what I'm testing in. The trouble is, every time I try, it prompts a download instead.
I'm using PHP sessions, so I know there are some extraneous headers being sent, so I called header_remove() to reset everything.
I call this function to show the PDF:
<?php
// For demonstrative purposes
session_start();
if (!isset($_SESSION['auth'])) {
header('Location: login.php');
die;
}
/*
* void viewPDF (Report $report)
* Outputs the PDF of the report
*/
function viewPDF ($report) {
// Tell the browser we are going to serve a PDF file.
$file = dirname(__FILE__).'/../reports/'.$report->id.'.pdf';
// The location of the PDF
if (!file_exists($file)) {
die ('The PDF does not exist.');
// Somehow the file does not exist.
}
header_remove();
// I'm using PHP sessions, so remove the headers
// automatically set that might break something.
header('Content-Disposition: inline;filename='.$report->id.'.pdf');
header('Content-Transfer-Encoding: binary');
header('Content-Type: application/pdf');
header('Content-Length: '.filesize($file));
readfile($file);
// Serve the report PDF file from the reports
// repository.
die;
// Any whitespace could corrupt the PDF, so be extra
// sure nothing else gets printed.
}
// For demonstrative purposes:
$report = new StdClass;
$report->id = 1;
viewPDF($report);
?>
These are the headers being sent:
Date: Tue, 08 Oct 2013 18:41:32 GMT
Server: Apache/2.2.22 (Win32) PHP/5.4.15
Content-Type: application/pdf
Content-Transfer-Encoding: binary
Content-Disposition: inline;filename=1.pdf
Connection: Keep-Alive
Keep-Alive: timeout=5, max=100
Content-Length: 73464
It's still prompting a download though. Once it downloads, I can open it in Adobe Reader just fine.
Am I missing something?
Thanks.
This code worked for me :
header('Content-Description: File Transfer');
header('Content-Type: application/pdf');
header('Content-Disposition: inline; filename="' . basename($file).'"');
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);

IE (HTTPS): generating pdf from php file doesn't work

Here is my issue. I am trying to call a page: foo.php?docID=bar and return a PDF to the screen which is stored as a BLOB in the DB.
Here is the portion of my code which actually returns the PDF:
$docID = isset($_REQUEST['docID']) ? $_REQUEST['docID'] : null;
if ($docID == null){
die("Document ID was not given.");
}
$results = getDocumentResults($docID);
if (verifyUser($user, $results['ProductId'])){
header('Content-type: application/pdf');
// this is the BLOB data from the results.
print $results[1];
}
else{
die('You are not allowed to view this document.');
}
This works perfectly fine in Firefox.
However, in IE, it doesn't show anything at all. If i'm on another page (i.e. google.com), and I type in the URL to go to this page, it will say it's done, but I will still have google.com on my screen.
I checked the headers for the responses from both firefox and IE. They are identical.
Does anyone have any suggestions? Need more information?
EDIT: If it helps at all, here's the response header and the first line of the content:
HTTP/1.1 200 OK
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Content-Length: 349930
Content-Type: application/pdf
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Server: Microsoft-IIS/6.0
X-Powered-By: PHP/5.1.2
Set-Cookie: PHPSESSID=cql3n3oc13crv3r46h2q04dvq4; path=/; domain=.example.com
Content-Disposition: inline; filename='downloadedFile.pdf'
X-Powered-By: ASP.NET
Date: Tue, 21 Apr 2009 16:35:59 GMT
%PDF-1.4
EDIT: Also, the page which pulls out the pdf file actually uses HTTPS instead of HTTP.
Thanks in advance,
~Zack
I figured out what the issue was. It's an IE bug dealing with IE, HTTPS and addons. (See here)
It was a caching issue. When I set:
header("Cache-Control: max-age=1");
header("Pragma: public");
(see here), the PDF was in cache long enough for the adobe reader add-on to grab it.
I had this issue too, i used the following which seems to work fine
header("Content-type: application/pdf");
header("Content-Length: $length");
header("Content-Disposition: inline; filename='$filename'");
Try this:
header("Content-Type: application/pdf");
header("Content-Disposition: inline; filename=foo.pdf");
header("Accept-Ranges: bytes");
header("Content-Length: $len");
header("Expires: 0");
header("Cache-Control: private");
Also, if you are using sessions, you can try setting
session_cache_limiter("none");
or
session_cache_limiter("private");
if ( USR_BROWSER_AGENT == 'IE' ) {
header( 'Content-Disposition: inline; filename="' . $name . '"');
header( 'Expires: 0' );
header( 'Cache-Control: must-revalidate, post-check=0, pre-check=0' );
header( 'Pragma: public' );
} else {
header( 'Content-Disposition: attachment; filename="' . $name . '"' );
header( 'Expires: 0' );
header( 'Pragma: no-cache' );
}
This was the only header I needed to change:
header("Pragma: public");
I think you need to add more headers.
header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");
header("Content-Disposition: attachment; filename=THEFILENAME.pdf;");
header("Content-Transfer-Encoding: binary");
header("Content-Length: " . strlen($results[1]));

Categories