I am having trouble with the download helper in ie..basically I built a site that dynamically creates pdf invoices and pdf proofs in both cases the force download works great in firefox, chrome and opera. In IE it fails everytime and I get the following error:
Unable to download $filename from mysite.com
Unable to open this Internet site. The requested site is either unavailable or cannot be found. Please try again later.
To begin the force_download I have a anchor target _blank with a url that directs to the following controller:
function view_uploaded_file($order = 0, $name = NULL){
$this->load->helper('directory');
$params['where'] = array('id' => id_clean($order));
$data['order'] = $this->MOrders->get($params);
if($data['order']->id < 1){
redirect('admin/orders');
}
$name = db_clean(urldecode($name));
$map = directory_map('./uploads/customer_order_uploads/'.$data['order']->user_id.'/'.$data['order']->id, 1);
if(is_array($map) && in_array($name, $map)){
$this->load->helper('download');
$data = file_get_contents('./uploads/customer_order_uploads/'.$data['order']->user_id.'/'.$data['order']->id.'/'.urldecode($name));
force_download($name, $data);
} else {
redirect('admin/orders');
}
}
Originally I thought maybe a problem with MY IE but I am able to download PDFs on other sites. I then thought that it could be a problem with codeigniters download helper but I see they already made special provisions for IE in the helper.
If you have any ideas please let me know. Thank you.
Frankly I am not sure why we bothered with a helper for downloads in code igniter.
It's not entirely hard to do in pure php:
This Wonderful Question/Answer outlines how to do it quite nicely.
The real thing to remember is the content-disposition: attachment part of the headers. It's what tells the browser that the file should be downloaded & saved vs. trying to show it in the browser.
All browsers handle things differently, maybe you have something in your IE install that's overriding the behaviour but if you follow the instructions in the linked article, you should get files downloaded correctly in all browsers.
Essentially there are 3 things we need to tell the browser:
Content Type
File Name
How to treat the incoming data
(Optional Fourth, if you have it) File Size (Content-Length)
Then you just dump that data right out to the output buffer.
Response
In response to your replies, it's probably a security feature to not automatically download something in a popup window, probably one of the new things IE introduced to combat their previous security holes.
Well I have found atleast a temporary fix for the problem. All my links for force downloads were target _blank..once I created standard non pop out links the file downloads worked in IE. There is probably some type of work around but I just also realized there is really no need for a pop up window for the download anyway..the download dialog box already serves that purpose.
Related
I have a PHP application that generates a CSV file and redirect the user to a static page linking to the file, just the example below :
https://www.example.com/public_html/static/temp/myfile.csv
Problem is, Chrome is opening the file instead of saving it. I need Chrome to save this file, as it would do with any other file like a zip or mp3, for instance.
Here is what I tried :
header('location:https://www.example.com/public_html/static/temp/myfile.csv');
header('Content-Disposition: attachment; filename=myfile.csv');
But no luck, Chrome keeps showing the myfile.csv contents instead of downloading it.
Any ideas ?
Thanks
Your argumentation in the comments has one never-ending misunderstanding: the Location header instructs any client to perform a new request to the given URI. With that the current request is over. Headers from the current request (i.e. Content-Disposition) aren't magically carried over to the next request.
In other words: your "static page linking to the file, just the example below" must send your wanted header.
Ultimately I'm sure it's not a Chrome problem either, but affects all internet browsers, as they easily detect the CSV data as text, hence being able to render/display that data instead of only being able to save it to a file.
With html5 you can set the "download" attr in an element.
Download it!
Source : http://updates.html5rocks.com/2011/08/Downloading-resources-in-HTML5-a-download
After struggling with this issue for some days, the only real solution i got is to ZIP the file and then redirecting to the ZIP file instead of the CSV. By doing this, Chrome will download the ZIP file instead of opening it :
header('location:https://www.example.com/public_html/static/temp/myfile.csv.zip');
I'm having a small problem with encrypted zip downloads in Safari. I've set all appropriate headers to force a download, but when the file's downloaded Safari tries to unzip it which results in a corrupt file. What I've read it's because Safari flags the file as safe and then tries to open it.
Is there a way to disable Safari from open the file after downloaded it?
You can't disable this server-side :(
It's Safari's default behavior to unpack archives after downloading them. This can be disabled in Safari: Preferences -> General -> Uncheck the box Open "safe" files after downloading at the bottom. But it's up to users themselves to do this.
If you like, you can display a warning about this behavior on the download page.
PS: The zip won't disappear! Safari may (optionally) unpack it, but the downloaded zip will still be next to the unpacked folder.
PPS: In 2022 (and according to the comments a couple years before) Safari will move the archive to the trash automatically. It's not completely deleted, but it's also not next to the unpacked folder anymore.
Definitely not the most elegant version there is but you may end up using a browser junction and have your download script change attachment name in combination with a notice for Safari users:
<?php
// $attachmentId used later-on would be a passed parameter that is used
// to define attachment name
$attachmentId= $_GET['id'];
$userAgent = $_SERVER['HTTP_USER_AGENT'];
if (strpos($userAgent , 'Chrome') === FALSE &&
strpos($userAgent , 'Safari') !== FALSE)
{
$attachmentName= 'download.zipname';
$userNotice= 'SAFARI users: please rename the file from download.zipname to download.zip (due to Safari\'s ZIP file policy (more info))';
} else {
$attachmentName= 'download.zip';
$userNotice= '';
}
?>
<span class="notice"><?php print $userNotice; ?></span>
Download
So basically before starting the download, you would set up this pre-download page to define the required attachment name and to inform safari users about what has to be done to successfully download the file.
I am afraid but you can't work this on the server side.
You can't help this. It's on the user to check or uncheck to open the downloaded files using the WinZip or some other software.
At the max we can do is show them an alert/popup suggesting the usage of this format is not safe or something on the similar lines.
You can use jQuery, where is safari you can hide or unhide a button or change the event of one button, etc.
if (jQuery.browser.mozilla){
// insert you code here
else if (jQuery.browser.msie){
// insert you code here
else if (jQuery.browser.safari){
// insert you code here
else if (jQuery.browser.opera){
// insert you code here
} else {
// insert you code here
});
So this is simple to understand what i want to achieve. So i get links like theese:
http://rockdizfile.com/atfmzkm7236t
http://rockdizfile.com/xuj5oincoqmy
http://rockdizfile.com/pg8wg9ej3pou
So theese links are from one cloud storage site I want to make a php script that automates their downloading.
So I can't find which is the script or the thing these links download button starts and how can I start that so i can download it with php on my server?
Basically my idea is to download a lot of files but don't wanna do it manually so need automatic way of doing it. As far as I know I make a request which is the following 2 urls:
http://rockdizfile.com/pg8wg9ej3pou
http://wi32.rockdizfile.com/d/wsli6rbhfp4r2ge4t7cqeeztijrprelfiw4afvqg5iwspmvqabpkmgiz/Desislava%20feat.%20Mandi%20&%20Ustata%20-%20Pusni%20go%20pak%20(CDRIP).mp3
So the first url is executing the next one but here comes the tricky part as far as I tested that last string Desislava%20feat.%20Mandi%20&%20Ustata%20-%20Pusni%20go%20pak%20(CDRIP).mp3 is the file name we get when downloading so if you change it with for example somefile.mp3 it will download somefile.mp3 but with the same file content as http://wi32.rockdizfile.com/d/wsli6rbhfp4r2ge4t7cqeeztijrprelfiw4afvqg5iwspmvqabpkmgiz/Desislava%20feat.%20Mandi%20&%20Ustata%20-%20Pusni%20go%20pak%20(CDRIP).mp3 so the data is hidden in this hash wsli6rbhfp4r2ge4t7cqeeztijrprelfiw4afvqg5iwspmvqabpkmgiz or i think so. And now is the tricky part how to get this hash? we have almost everything we have the code for the url atfmzkm7236t the hash wsli6rbhfp4r2ge4t7cqeeztijrprelfiw4afvqg5iwspmvqabpkmgiz and the filename Desislava%20feat.%20Mandi%20&%20Ustata%20-%20Pusni%20go%20pak%20(CDRIP).mp3 There must be a way to download from this site without clicking so please help me kinda a hack this :)
you can use PHP's header function to force a file to download
header('Content-disposition: attachment; filename=index.php');
readfile('Link');
You should know that this will not give you the ability to download PHP files from external websites.
You can only use this if you got the direct link to a file
It's impossibly to tell you without the source code
e.g. sha1("Test Message") gives you 35ee8386410d41d14b3f779fc95f4695f4851682 but sha256("Vote this up") gives you 65e03c456bcc3d71dde6b28d441f5a933f6f0eaf6222e578612f2982759378ed
totally different... unless you're hidden function add's "65e03c456bcc3d71dde6b28dxxxxxxxxxxxxxxxxxxxxxxxxxx" (where xxxxxxxxxxxxxxxxxxxxxxxxxx is a bunch of numbers I can't be arsed to work out) to each hash...
then sha1("Test Message") gives you 65e03c456bcc3d71dde6b28d441f5a933f6f0eaf6222e578612f2982759378ed
The file is embedded into the swf player.
alert(jwplayer('mp3player').config.file);
Something like:
<?PHP echo file_get_contents($_GET["url"]); ?>
<script>
document.location=jwplayer('mp3player').config.file;
</script>
Though I've actually just noticed they change 5 digits of the URL on each page request, and the script above uses 2 page requests. One to get the URL and HTML source and another to try and download the file, meaning the URL has changed before the second request has started.
Lets say i have this string "something1,something2" and i want to download it as "text.csv", without opening new window (pop up) how could i do this from a webpage. can i dot it in JS without using this:
window.open('data:text/csv;charset=utf-8,' + str);
or do i have to use PHP for this ?
What you want to do is a bit unconventional, but it is possible.
Take a look at Downloadify. It's a JavaScript library that leans on Flash to create a file on the client side and present the file download dialog.
David Walsh has some good demos and info too on his blog.
While limited, there is also http://en.wikipedia.org/wiki/Data_Uri
So this as a url would open an image
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==
You could have javascript open this url to trigger the download
A CSV example
data:text/csv,field1%2Cfield2%0Afoo%2Cbar%0Agoo%2Cgai%0A
Just copy/paste either of those into your browser to see them work. Browser support is limited.
IE 8 for example has a 32KiB limit
On a PHP-based web site, I want to send users a download package after they have filled out a short form. The site-initiated download should be similar to sites like download.com, which say "your download will begin in a moment."
A couple of possible approaches I know about, and browser compatibility (based on a quick test):
1) Do a window.open pointing to the new file.
- FireFox 3 blocks this.
- IE6 blocks this.
- IE7 blocks this.
2) Create an iframe pointing to the new file.
- FireFox 3 seems to think this is OK. (Maybe it's because I already accepted it once?)
- IE6 blocks this.
- IE7 blocks this.
How can I do this so that at least these three browsers will not object?
Bonus: is there a method that doesn't require browser-conditional statements?
(I believe that download.com employs both methods conditionally, but I can't get either one to work.)
Responses and Clarifications:
Q: "Why not point the current window to the file?"
A: That might work, but in this particular case, I want to show them some other content while their download starts - for example, "would you like to donate to this project?"
UPDATE: I have abandoned this approach. See my answer below for reasons.
You can also do a meta refresh, which most browsers support. Download.com places one in a noscript tag.
<meta http-equiv="refresh" content="5;url=/download.php?doc=123.zip"/>
Update: I have decided to abandon this approach, and instead just present the user with a link to the actual file. My reasoning is this:
My initial attempts at a server-initiated download were blocked by the browser. That got me thinking: "the browser is right. How does it know that this is a legitimate download? It should block a download that isn't obviously user-initiated."
Any method that I can use for a server-initiated download could also be used by someone who wants to send malware. Therefore, downloads should only happen when the user specifically requests the file by clicking on a link for it.
You're free to disagree, and if you still want to initiate a download, hopefully this thread will help you do it.
I usually just have a PHP script that outputs the file directly to the browser with the appropriate Content-Type
if(file_exists($filename)) {
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, pre-check=0");
header("Cache-Control: private", false);
header("Content-Type: " . $content-type);
header("Content-Disposition: attachment; filename=\"" . basename($filename) . "\";" );
header("Content-Transfer-Encoding: binary");
header("Content-Length: " . filesize($filename));
readfile("$filename");
}else{
print "ERROR: the file " . basename($filename) . " could not be downloaded because it did not exist.";
}
The only disadvantage is that, since this sets the HTTP header, it has be called before you have any other output.
But you can have a link to the PHP download page and it will cause the browser to pop up a download box without messing up the content of the current page.
One catch is that you may encounter issues with IE (version 6 in particular) if the headers are not set up "correctly".
Ensure you set the right Content-Type, but also consider setting the Cache options for IE (at least) to allow caching. If the file is one the user can open rather than save (e.g. an MS Word document) early versions of IE need to cache the file, as they hand off the "open" request to the applicable app, pointing to the file that was downloaded in the cache.
There's also a related issue, if the IE6 user's cache is full, it won't properly save the file (thus when the applicable app gets the hand off to open it, it will complain the file is corrupt.
You may also want to turn of any gzip actions on the downloads too (for IE)
IE6/IE7 both have issues with large downloads (e.g. 4.x Gigs...) not a likely scenario since IE doesn't even have a download manager, but something to be aware of.
Finally, IE6 sometimes doesn't nicely handle a download "push" if it was initiated from within a nested iframe. I'm not exactly sure what triggers the issue, but I find it is easier with IE6 to avoid this scenario.
Hoi!
#Nathan:
I decided to do exactly that: Have my "getfile.php" load all necessary stuff and then do a
header("Location: ./$path/$filename");
to let the browser itself and directly do whatever it thinks is correct do with the file. This even works fine in Opera with me.
But this will be a problem in environments, where no direct access to the files is allowed, in that case you will have to find a different way! (Thank Discordia my files are public PDFs!)
Best regards, Basty
How about changing the location to point to the new file? (e.g. by changing window.location)
I've always just made an iframe which points to the file.
<iframe src="/download.exe" frameborder="0" height="0" width="0">Click here to download.</iframe>
Regarding not pointing the current window to the download.
In my experience you can still show your "please donate" page, since downloads (as long as they send the correct headers) don't actually update the browser window.
I do this for csv exports on one of my sites, and as far as the user is concerned it just pops up a safe file window.
So i would recommend a simple meta-redirect as Soldarnal showed.
Just to summarise, you have 2 goals:
start download process
show user a page with a donate options
To achieve this I would do the following:
When your user submits the form, he gets the resulting page with a donate options and a text saying that his download will start in 5 seconds. And in the head section of this page you put the META code as Soldarnal said:
<meta http-equiv="refresh" content="5;url=/download.php?doc=123.zip>
And that's all.
<a href="normaldownload.zip" onclick="use_dhtml_or_ajax_to_display_page()">
Current page is unaffected if download is saved. Just ensure that download doesn't open in the same window (proper MIME type or Content-Disposition) and you'll be able to show anything.
See more complete answer
You can use Javascript/jQuery to initiate the download. Here's an example - you can get rid of the Ajax request and just use the setTimeout() block.
$("btnDownloadCSV").on('click', function() {
$.ajax({
url: "php_backend/get_download_url",
type: 'post',
contentType: "application/x-www-form-urlencoded",
data: {somedata: "somedata"},
success: function(data) {
// If iFrame already exists, remove it.
if($("[id^='iframeTempCSV_"]).length) {
$("[id^='iframeTempCSV_"]).remove();
}
setTimeout(function() {
// If I'm creating an iframe with the same id, it will permit download only the first time.
// So randHashId appended to ID to trick the browser.
var randHashId = Math.random().toString(36).substr(2);
// Create a fresh iFrame for auto-downloading CSV
$('<iframe id="iframeTempCSV_'+randHashId+'" style="display:none;" src="'+data.filepath+'"></iframe>').appendTo('body');
}, 1000);
},
error: function(xhr, textStatus, errorThrown) {
console.error("Error downloading...");
}
});
});