i have a files for download mysql database using php.which is working properly.but i want to download codes to specific folder created in D drive
$backup_file_name = $database_name . '_backup_' . time() . '.sql';
$fileHandler = fopen($backup_file_name, 'w+');
$number_of_lines = fwrite($fileHandler, $sqlScript);
fclose($fileHandler);
// Download the SQL backup file to the browser
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' . basename($backup_file_name));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($backup_file_name));
file_put_contents('D:\dbbackups', $backup_file_name);
ob_clean();
flush();
readfile($backup_file_name);
exec('rm ' . $backup_file_name);
but file id download inside the project folder.any help would be highly appreciated
From PHP, you can't.
Your server-side PHP application has no knowledge of, or control over, the application or device which is making the HTTP request. All it does it return some data and headers to the requesting client.
Your server / PHP has no idea whether
the client device even has a D: drive (or even runs an O/S which uses drive letters), or whether a specific folder exists within it
the client will even treat the response as a file and try to save it somewhere
And even if it did know the above, then
your server would have no permissions to access the client-side device or its storage media.
If what you're suggesting was possible it would be a big security / privacy problem. But it would still be impractical even then, because of my first point.
What you can do to help yourself in this situation though is to write your own client-side program which makes the HTTP request to your server to execute the PHP, receives the data in the response and saves it to the location you want. Or if you're doing this via a browser you can set the browser's default download location to that folder.
Related
I have many files stored in a NAS. The NAS is attached to a server as network drive (lets say, it is on Y://).
I use xampp to serve my application built in php. The application was built to serve users to download the files from NAS, directly through http instead of ftp.
So can I set the files from NAS, so it can be downloaded by using http URL, like example.com/files/the-file.zip ?
The xampp is located at C:// directory
Note: The xampp htdocs has already set to accessed by a domain. So it is not domain pointing problem
You could try so through PHP:
<?php
$downloadFolder = 'Y:/';
$fileName = $downloadFolder . $_GET['file'];
$sanitizedFileName = realpath($fileName);
if($fileName !== $sanitizedFileName) {
throw new RuntimeException('Someone tried to escape');
}
// As seen in http://php.net/readfile:
if (file_exists($fileName)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($fileName).'"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($fileName));
readfile($fileName);
exit;
}
Or find a way to run everything through .htaccess, but that might give you less control over security handling (probably, you don't want to serve files from other directories or other drives)
For some reason, our webserver is not responding while it's serving large files.
We use the windows platform, because we need to remotely call Win32 applications in order to generate the file that is to be served. This file is served through PHP's function: fpassthru, using this code:
if (file_exists($file)) {
$handle = #fopen($file, "rb");
header('Content-Description: File Transfer');
header('Content-Type: video/mp4');
if($stream==0){
header('Content-Disposition: attachment; filename='.basename($filename.".mp4"));
}
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_end_clean();
fpassthru($handle);
exit;
}
These files are often over 1GB in size and takes a while to transfer, but during this time, the webserver will not serve any pages. My firefox indicates it's 'connecting' but nothing else. Note that somebody else is transferring this file, not me, so different IP, different session.
Any clue where to look? Obviously, it's intolerable to have to wait 5 minutes for a website.
Thanks in advance!
This is commonly caused when you do not close the session before you begin sending the file data. This is because the session cache file can only be opened by one PHP process at a time, therefore the download is effectively blocking all other PHP processes at session_start().
The solution is to call session_write_close() to commit the session data to disk and close the file handle before you start outputting the file data.
I have a PHP script that is currently working locally that I'd like to put on a server.
Currently, the user choose a .txt file, the PHP script works on it and outputs a new file based on what it read in the file.
The problem is that I can only select files in the folder with the script, and not elsewhere.
I use a to get the file name, but it only gives out the name of the file, and not it's absolute path.
From what I've read, I think that I need to upload the file to the server, process it with the script and then give it back to the user.
I'm not sure this is the correct method though.
Also, while I have found plenty of informations on uploading files to the server, I don't know how to put the new file created by the script in the folder where the original file is located.
You cannot read or write files directly on the client's machine. The client will need to upload the file by selecting it in the browser, the server receives the data, processes the data and returns data. This returned data can be presented in the form of a file download by setting the appropriate HTTP headers. The client will have to acknowledge the file download and save it somewhere of his choosing.
Your server has no business knowing anything about files or folders on the client's machine. It can only communicate with it over the HTTP protocol and send and receive data.
You will have to give the file back to the client, as a downloadable file. You can "write" it to the user by setting some headers. Take a look:
<?php
$file = 'random_text_file.txt';
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; 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);
exit;
}
?>
That will prompt a download of the file to the user.
I have an mp3 on my server (urls are just examples):
http://www.my-server.com/myaudio.mp3
I have a php script on the server at:
http://www.my-server.com/testmp3.php
Which contains the following code (which I got here):
<?
$file = "myaudio.mp3";
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
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($file));
ob_clean();
flush();
readfile($file);
exit;
}
?>
Is this all I have to do to mimic the behavior so that both request behave the same way and return the exact same response? Or is there anything I'm missing.
I'm using some streaming code on iOS (not relevant here) and both requests stream the audio fine but I can't seek properly using the php request but I can with the mp3 request directly.
So without getting into details about the app itself I wanted to eliminate this one variable first. Is there anything I need to do to make sure that from another app's perspective these two request will return the exact same data?
Thanks for any input you can give me here.
Update
It turns out my question really should have read "how do you support seeking of an mp3 when returning from a php script?".
To support seeking, you often will have to support a range request.
From the RFC: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35
See also: Resumable downloads when using PHP to send the file?
Its probably better to handle this with a .htaccess modification rather than some PHP code.
Here's a link on htaccess to get you started.
If you have a whole directory of .mp3 files that you want to appear as downloads instead of playing it in browser, you'd simply modify the .htaccess file in that folder to include
AddType application/octet-stream .mp3
I am using the simple file downloading script:
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
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($file));
ob_clean();
flush();
readfile($file);
exit;
}
It is working on my localserver upto 200mb.
When i try this code in my website it downloads 173KB instead of 200MB file.
I checked everything, wrote some custom code (using ob functions and fread instead of readfile) but can't download big files.
Thank you for your answers.
I am using Apache 2.2, PHP 5.3
All PHP settings to deal with big files are ok. (execution times, memory limits, ...
One issue I have with the following code is you have no control over the output stream, your letting PHP handle it without knowing exactly what is going on within the background:
What you should do is set up an output system that you can control and replicated accros servers.
For example:
if (file_exists($file))
{
if (FALSE!== ($handler = fopen($file, 'r')))
{
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: chunked'); //changed to chunked
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
//header('Content-Length: ' . filesize($file)); //Remove
//Send the content in chunks
while(false !== ($chunk = fread($handler,4096)))
{
echo $chunk;
}
}
exit;
}
echo "<h1>Content error</h1><p>The file does not exist!</p>";
This is only basic but give it a go!
Also read my reply here: file_get_contents => PHP Fatal error: Allowed memory exhausted
It seems readfile can have issues with long files. As #Khez asked, it could be that the script is running for too long. A quick Googling resulted in a couple examples of chunking the file.
http://teddy.fr/blog/how-serve-big-files-through-php
http://www.php.net/manual/en/function.readfile.php#99406
One solution to certain scenarios is that you can use PHP-script to intelligently decide what file from where to download, but instead of sending the file directly from PHP, you could return a redirection to the client which then contains the direct link which is processed by the web server alone.
This could be done at least in two ways: either PHP-script copies the file into a "download zone" which for example might be cleaned from "old" files regularly by some other background/service script or you expose the real permanent location to the clients.
There are of course drawbacks as is the case with each solution. In this one is that depending on the clients (curl, wget, GUI browser) requesting the file they may not support redirection you make and in the other one, the files are very exposed to the outer world and can be at all times read without the (access) control of the PHP script.
Have you made sure your script can run long enough and has enough memory?
Do you really need output buffering ?
The real solution is to avoid using a PHP script for just sending a file to the client, it's overkill and your webserver is better suited for the task.
Presumably you have a reason for sending the files through PHP, perhaps users must authenticate first? If that is the case then you should use X-Accel-Redirect (if you're using nginx) or X-Sendfile (previously X-LIGHTTPD-send-file) on lighttpd.
If you're using Apache I've found a few references to mod_xsendfile but I've never used it personally, and I doubt it's installed for you if you have managed hosting.
If these solutions are untenable I apologise, but I really need more information on the actual problem: Why are you sending these files through PHP in the first place?