Here is my code:
Server Side:
public function export(){
$arr = array();
if($_POST["type"] == "save"){
$name = "export.txt";
file_put_contents("$name",$_POST["text"]);
$arr["type"] = "link";
$arr["url"] = "http://localhost:8000/{$name}";
}
return $arr;
}
Client Side:
$(document).on('click', '#export', function () {
var names = ["سعید خرمی", "فرید هادوی"];
var namess = names.join('\n');
$.ajax({
type: "post",
url: "/export",
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
data: {
type: "save",
text: namess
},
dataType: "json",
success: function(data){
var href = data.url;
window.location = href;
}
});
})
When I click on #export (button), it opens that .txt file (instead of downloading it). Something like this:
Noted that I use chrome .. Also it doesn't work in other browsers.
How can I force it to download that .txt file?
Change your success part like this,
success: function(data){
var href = download.php?filename=export.txt;
window.location = href;
}
And in your download.php:
Get the file name from the GET variable filename (say as $file).
Send the headers:
<?php
$file = $_GET['filename']; // get the filename
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: text/plain'); // the appropriate header type for txt file
header('Content-Disposition: attachment; filename="'.basename($file).'"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
readfile($file);
exit;
}
?>
Source: PHP Readfile Documentation
Related
So I'm making a Image gallery site, and I have a bunch of buttons such as approve image, and download image, which call the JS function "runAJAX" and based on the request type, the php is supposed to prefore a specific task. The issue I'm having is that the AJAX function is saying it's successfully run, but the php file is not being run. When I run it, "Request Completed" prints but no txt file is created like it supposed to. Any help would be greatly appreceated. Thank you very much.
// imageID is an int of the image UID
// request is a string that describes the button (approve, download etc.)
function runAJAX(imageID, request) {
// myArr is a JSON array
var myArr = allJSON;
console.log("UID is" + imageID);
for (var i = 0; i < myArr.length; i++){
if (myArr[i].UID == imageID){
switch (request) {
case "approve": myArr[i].approved = "true"; console.log("Approve was set to true"); break;
case "download": console.log("Image will be downloaded"); break;
default: console.log("No action will be done for this request");
} // switch
} // if
} // for
$.ajax({
type: "POST",
url: 'requestAJAX.php',
data: {request: request, newJSON: JSON.stringify(myArr), download: imageID},
success: function(){
console.log("Request Completed: " + request);
window.location.reload(false);
} // success
});
} // runAJAX
requestAJAX.php
<?php
switch ($_POST["request"]) {
case "approve":
// output to checking to see what the request is
touch("AJAXtest.txt");
file_put_contents("AJAXtest.txt", $_POST["request"]);
unlink("test.json");
$stringyJSON = json_decode($_POST["newJSON"], true);
$finalJSON = json_encode($stringyJSON, JSON_PRETTY_PRINT);
$file = "galleryinfo.json";
touch($file);
file_put_contents($file, $finalJSON);
break;
case "download":
// output for checking to see what the request is
touch("AJAXtest.txt");
file_put_contents("AJAXtest.txt", $_POST["request"]);
// Get parameters
$file = $_POST["download"];
$filepath = "UploadedImages/" . $file;
if(file_exists($filepath)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($filepath).'"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($filepath));
flush(); // Flush system output buffer
readfile($filepath);
exit;
} // if
break:
default:
// output for checking to see what the request is
touch("AJAXtest.txt");
file_put_contents("AJAXtest.txt", "No request made");
echo "No request was made";
}
?>
this simple ajax call works fine in Chrome, FF, Safari :
function downloadEntryReport() {
var data_range = document.getElementById("daterange").value;
var ajax_url = "ajaxcalls/download_entry_report/"+data_range;
$.ajax({
cache: false,
type: 'POST',
url: ajax_url,
dataType: 'text',
error: function(){
alert('Error loading document');
return false;
},
success: function(data) {
document.location.href = "ajaxcalls/download_entry_report/"+data_range;
}
});
}
except in IE (tested in 9.0.8). IE opens the URL (ajaxcalls/download_entry_report/given_date_range) which of course returns a 404 error. Is there a hack around this issue in IE or am I missing something?
Appreciate your help!
Here's the called PHP function :
function download_entry_report($data_range) {
$date_range_array = explode("%20::%20", $data_range);
$start_date = $date_range_array[0];
$end_date = $date_range_array[1];
$query = $this->db->query("SELECT * FROM tbl_name WHERE created_by = '".$this->session->userdata('email')."' AND DATE_FORMAT(created_date, '%Y-%m-%d') BETWEEN '".$start_date."' AND '".$end_date."' ");
$results = $query->result_array();
echo $this->download_csv_results($results, 'entry_report.csv');
exit();
}
and the other function to download the csv file :
function download_csv_results($results, $name = NULL)
{
if( ! $name)
{
$name = md5(uniqid() . microtime(TRUE) . mt_rand()). '.csv';
}
header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename='. $name);
header('Pragma: no-cache');
header("Expires: 0");
$outstream = fopen("php://output", "w");
foreach($results as $result)
{
fputcsv($outstream, $result);
}
fclose($outstream);
}
Here is my code:
PHP:
public function export(Request $request){
$file = "export.txt";
if(isset($_POST["type"])){
file_put_contents("$file",$_POST["text"]);
}
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: text/plain'); // the appropriate header type for txt file
header('Content-Disposition: attachment; filename="'.basename($file).'"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
readfile($file);
exit;
}
}
JS:
$(document).on('click', '#export', function () {
var names = ['علی','فرید'];
var namess = names.join('\n');
$.ajax({
type: "post",
url: "/export",
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
data: {
type: "save",
text: namess
},
dataType: "json",
success: function(){
var href = '/export?filename=export.txt';
window.location = href;
},
error: function(){
alert('wrong');
}
});
})
Always error part executes. I mean it always alert wrong. How can I fix it? All I'm trying to do it making a .txt download file.
Noted that when I run this path: http://localhost:8000/export?filename=export.txt .. then export.txt will be downloaded.
You can download using this code:
window.location="export?filename=export.txt";
If you want to post data :
$('<form action="comments.php" method="POST"/>')
.append($('<input type="hidden" name="type" value="save">'))
.append($('<input type="hidden" name="text" value="'+ namess +'">'))
.appendTo($(document.body)) //it has to be added somewhere into the <body>
.submit();
Full code:
$(document).on('click', '#export', function () {
var names = ['علی','فرید'];
var namess = names.join('\n');
$('<form action="export?filename=export.txt" method="POST"/>')
.append($('<input type="hidden" name="type" value="save">'))
.append($('<input type="hidden" name="text" value="'+ namess +'">'))
.appendTo($(document.body)) //it has to be added somewhere into the <body>
.submit();
});
});
Basically Ajax is not usually used for file download however you can tune to make it feel and that is what you have done the only thing is when the request is successful us a "document.location" function from javascript to popup a new window for downloading a file. Besides for the error you are getting, try debugging your PHP code by playing around with your PHP header by starting with most important PHP Headers such as
header('Content-Type: text/plain');
header('Content-Disposition: attachment;filename="'.basename($file).'"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
ob_clean();
flush();
readfile($fileName);
exit;
check you code works with minimal information if it works then start adding more header one at a time, this helps in resolving problem with minimal information.
Hope this helps.
I am saving a file constructed in javascript to the local internet downloads directory.
This works:
javascript
var filename = "mysave.txt"
var contents = "xyz";
document.location = "htmlsave.php?filename=" + filename + "&contents=" + contents;
htmlsave.php:
if(!isset($_GET)) {
exit(0);
}
$filename = $_GET['filename'];
$contents = $_GET['contents'];
header("Pragma: public"); // required
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private", false); // required for certain browsers
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"" . $filename . "\";" );
header("Content-Transfer-Encoding: binary");
header("Content-Length: " . strlen($contents));
header("Connection: close");
echo $contents;
This does not:
javascript:
var i;
var filename = "mysave.txt"
var contents = "";
for(i=0, contents = "";i<10000;i++){
contents += "x";
}
document.location = "htmlsave.php?filename=" + filename + "&contents=" + contents;
This obviously does not work due to the 2K limit on the url.
The error is:
Request-URI Too Long
The requested URL's length exceeds the capacity limit for this server.
Obviously you need to use POST, but how do you do it with POST? How do you do the 'document.location =' bit with POST data? You cannot do an ajax POST, (see below), I have tried it and it does not work.
The failed POST method:
javascript:
var filename = "mysave.txt"
var contents = "";
for(i=0, contents = "";i<10000;i++){
contents += "x";
}
dataARR = {
filename: filename,
contents: contents
};
var dataJSON = JSON.stringify(dataARR);
$.ajax({
type: "POST", // This for array
url: "htmlsave.php",
async: true,
cache: false,
crossDomain: false, // This needs to be true for other people
data: { myJson: dataJSON },
success: function (data) {
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
}
});
htmlsave.php
if(!isset($_POST) || !isset($_POST['myJson'])) {
exit(0);
}
$dataTotal = json_decode($_POST['myJson'], true);
$filename = $dataTotal['filename'];
$contents = $dataTotal['contents'];
header("Pragma: public"); // required
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private", false); // required for certain browsers
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"" . $filename . "\";" );
header("Content-Transfer-Encoding: binary");
header("Content-Length: " . strlen($contents));
header("Connection: close");
echo $contents;
So what can I do to save files greater than 2K?
php is not necessary to create, prompt user to save file created at javascript. You can use <a> element with download attribute set to filename, href set to objectURL of Blob containing file data to initiate prompt for user to save file.
If you want to use php you can utilize php://input, file_get_contents(), echo POSTed Blob or File object.
var i;
var filename = "mysave.txt"
var contents = "";
for(i=0, contents = "";i<10000;i++){
contents += "x";
}
var data = new Blob([contents], {type:"text/plain"});
var file = URL.createObjectURL(data);
var a = document.createElement("a");
a.download = filename;
a.href = file;
a.click();
Using file_ge_contents(), php://input
javascript
var i;
var filename = "mysave.txt"
var contents = "";
for(i=0, contents = "";i<10000;i++){
contents += "x";
}
var data = new Blob([contents], {type:"text/plain"});
var request = new XMLHttpRequest();
request.open("POST", "/path/to/server");
request.setRequestHeader("x-file-name", filename);
request.reponseType = "blob";
request.onload = function() {
console.log(this.response); // `echo`ed file
};
request.send(data);
php
echo file_get_contents("php://input");
See also Generate png-file with php from dataURI sent through ajax ; though note request.setRequestHeader("x-file-name", filename); should have been included at javascript portion of Answer for $tmpFilename = $_SERVER["HTTP_X_FILE_NAME"]; at php
I'm developing an SVG editor. I have to save the svg picture on the local disk. As you know, for safety reasons, it is impossible do it directly with javascript. So I decided to approach the problem with the server side help. I wrote the following PHP routine in a file called "savefile.php":
<?php
$mime = array('xls' => 'application/vnd.ms-excel', 'xml' => 'application/xml', 'html' => 'text/html', 'cvs' => 'text/plain', 'svg' => 'text/plain', 'txt' => 'text/plain', 'json' => 'text/plain', 'array' => 'text/plain');
if (isset($_POST['format']) && isset($_POST['filename']) && isset($_POST['content'])) {
$filename = $_POST['filename'];
$format = $_POST['format'];
$content = $_POST['content'];
$fullName = $filename . '.' . $format;
header('Pragma: public');
header("Content-Description: File Transfer");
header("Content-Transfer-Encoding: binary");
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header("Cache-Control: public");
header('Content-Type: ' . $mime[$format]);
header('Content-Disposition: attachment; filename="' . basename($fullName) . '"');
echo $content;
}
?>
On the server side I call, the PHP procedure, with this code:
var obj = {
format: 'svg',
filename: 'myfilename',
content: glb.Draw_active().GetDisegno().svg()
};
$.post("php/savefile.php",obj,function(data,status,xhr){console.log('Executed');});
When the software execute the above code, the browser should open the savefile window and wait the confirm from the user..... but nothing happens. I'm sure that the PHP routine is executed, it is also executed the callback routine, but nothing else.
Something is wrong, my suspect is on the javascript client-side code but I'm not able to find any documentation. May be someone have experience on this procedure?
Thanks a lot.
Thanks to #Quentin for the help I have solved the problem. The PHP code above is working, I had to change the Javascript part. Here the working code:
The SaveFile routine:
/*
#datatype : 'svg', 'xml', 'txt', 'xls', 'csv', 'html', etc see the list in PHP file
#filename : filename without extension
#exportServer : name of the PHP file on the server
#content : content of the file to save
*/
var saveFile = function(datatype, filename, exportServer,content){
var HInput = function(value, name, form) {
var I = document.createElement('input');
I.name = name;
I.value = value;
I.type = 'hidden';
form.appendChild(I);
},
HTextArea = function(value, name, form) {
var tA = document.createElement('textarea');
tA.name = name;
tA.value = value;
form.appendChild(tA);
};
var form = document.createElement('form');
HInput(filename, 'filename', form);
HInput(format, 'format', form);
HTextArea(content, 'content', form);
form.action = exportServer;
form.method = 'post';
document.body.appendChild(form);
form.submit();
document.body.removeChild(form);
}
.... for my need I call it in this way:
saveFile('svg','myfilename',"php/savefile.php",data);
thats all...... ;)