Swift downloading files from PHP headers - php

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?

Related

File Download using PHP/Apache2 and Google Chrome

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.

Browser halt for the site during file download

I have small chunk of code that helps to download a file. But the site not opened/work during file download, but when i open the site on other browser then its working. I don't have any idea what going on with the browser during file download. Here are the headers that i am using to download a zip file:
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("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);
ob_end_clean();
Even i don't know how to debug it, so that i get the weak point from my codes.
So since you are using sessions:
An “open” session blocks other scripts from accessing the session while your download script is running.
session_write_close before streaming the file content to the client fixes that. Just call it after you are done with checking whatever you need to check in the session, and before the time-consuming part of the script begins – that will release the lock on the session, and other scripts that are called while the download script is running can access the session again.

Large file download taking more time

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.

Script to Download File from Android Browser

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.

how we can delete cache forcefully when user logs-in using javascript

Can anybody tell me how we can delete browser cache using javascript. I want this because I am giving user, file for download with url ('http://www.example.com/docs/doc1.xlsx'). and this files are accessible for that specific user only.
I am checking with htaccess redirect to other action which redirect to that specific file url if user does not have access then Access Denied page come.
But problem is when valid user download that file and logs out from application and copied above url and hit enter on browser file gets for download without accessing to server, which happens due to caching in browser.
So I want to delete cache when user logs out of system.
Alternative solutions are most welcome.
In short, you can't (or, at least, I have never seen a way of doing it).
You'll need to do it on the server side by sending the correct cache-busting headers. Something like:
Cache-Control: no-cache, must-revalidate, max-age=0
You can do this using (to steal an example from the PHP documentation):
header("Cache-Control: no-cache, must-revalidate, max-age=0");
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT");
This is not possible. Php only works serverside and using javascript is not working because of security issues. ActiveX is not an option eigther i guess.
What you can do is to attach a no-cache header for a page that must reload each time.
Rather than giving direct access to the file (as you mentioned "http://www.example.com/docs/doc1.xlsx"), I think you should read the the file in php and give it for download after checking for the valid user..
Example taken from php.net
<?php
// downloading a file
$filename = $_GET['path'];
/**
* YOU CAN CHECK YOUR VALIDATIONS HERE..
*
*
*
*/
// fix for IE catching or PHP bug issue
header("Pragma: public");
header("Expires: 0"); // set expiration time
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
// browser must download file from server instead of cache
// force download dialog
header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");
// use the Content-Disposition header to supply a recommended filename and
// force the browser to display the save dialog.
header("Content-Disposition: attachment; filename=".basename($filename).";");
/*
The Content-transfer-encoding header should be binary, since the file will be read
directly from the disk and the raw bytes passed to the downloading computer.
The Content-length header is useful to set for downloads. The browser will be able to
show a progress meter as a file downloads. The content-lenght can be determines by
filesize function returns the size of a file.
*/
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize($filename));
#readfile($filename);
exit(0);
?>
Hope this helps..
Thanks...
I have resolved issue without major modifications.
Firstly I tried by setting header as you people suggested. Before redirecting for file to download I tried to set header for cache-control, but it doesn't work at all.
So I stretch my mind more and find simple solution by setting headers in .htaccess file which is located in folder where all downloadable files are located. That means cache-control header is set to download files response.
But still one thing in mind why above solutions not working.
And one more thing Pragma: "no-cache" not working for IE. that is it gives error while downloading requested file as "requested site is unavailable or cannot be found".
So I have set it to Pragma: public. But I doubt whether it is secure.

Categories