extjs Hidden form after download not firing success - javascript

Scouring the net for how to separate the download data from the success/fail data when doing a download using a standardsubmit in extjs, and can't find anything specific about how to do this.
For example, I have a hidden form that I am using to force a download:
var hiddenForm = Ext.create('Ext.form.FormPanel', {
standardSubmit: true,
height: 0,
width: 0,
hidden: true
});
hiddenForm.getForm().submit({
url: 'downloadtxt.php',
method: 'POST',
success: function(form, action) {
console.log('success');
},
failure: function(form, action) {
console.log('failure');
}
});
and on the server in PHP I have this code:
$file_name = "test.txt";
$file_data = "The text to save in the file";
header("Content-Type: " . "text/plain");
header("Content-Length: " . strlen($file_data));
header("Content-Disposition: attachment; filename=\"" . $file_name . "\"");
$result["success"] = true;
$result["errors"] = array();
$result["data"] = $file_data;
echo json_encode($result);
In this case, the entire contents of the $result array gets put into the download file (effectively buggering the contents, and additionally the success/fail methods never get called in the submit() code. Now, if I change the PHP server code to:
$file_name = "test.txt";
$file_data = "The text to save in the file";
header("Content-Type: " . "text/plain");
header("Content-Length: " . strlen($file_data));
header("Content-Disposition: attachment; filename=\"" . $file_name . "\"");
echo $file_data;
then the downloaded file contains what I expected ("The text to save in the file"), but the success/fail methods still never get called in the submit() code. How is it possible to trigger the success/fail code, but yet not bugger up the contents of the download file?

Related

How do I send a Blob of type octet/stream to server using AJAX?

I have unsuccessfully been trying to send a Blob file (which is an .OBJ file type) to the server using AJAX. I want to be able to do this without using an input file field. I am making an online avatar creator, so the Blob file to be sent to the server is generated from the character that is initially imported into my Three.js scene. I have been able to send a Blob file that contains a String to the server and save this to a specified folder (which I am aiming to do with the Blob .OBJ file). I have tried converting the Blob to Base64 before sending it in a POST request, but this did not work. The size of the file that I am trying to send is 3MB.
Here is my JavaScript code for creating the Blob file and sending it to my PHP script on the server using AJAX.
//Create OBJ
var exporter = new THREE.OBJExporter();
var result = exporter.parse(child);
//Generate file to send to server
var formData = new FormData();
var characterBlob = new Blob([result], {type: "octet/stream"});
var reader = new FileReader();
reader.readAsDataURL(characterBlob);
reader.onloadend = function() {
formData.append('file', reader.result);
$.ajax({
url: "ExecuteMaya.php", // Url to which the request is send
type: "POST", // Type of request to be send, called as method
data: formData, // Data sent to server, a set of key/value pairs (i.e. form fields and values)
processData:false, // To send DOMDocument or non processed data file it is set to false
contentType: false, // The content type used when sending data to the server
}).done(function(data) {
console.log(data);
});
}
Here is my PHP script for handling the sent file.
<?php
$sourcePath = $_FILES['file']['tmp_name']; // Storing source path of the file in a variable
$targetPath = "upload/".$_FILES['file']['name']; // Target path where file is to be stored
move_uploaded_file($sourcePath,$targetPath) ; // Moving Uploaded file
echo "<span id='success'>Image Uploaded Successfully...!!</span><br/>";
echo "<br/><b>File Name:</b> " . $_FILES["file"]["name"] . "<br>";
echo "<b>Type:</b> " . $_FILES["file"]["type"] . "<br>";
echo "<b>Size:</b> " . ($_FILES["file"]["size"] / 1024) . " kB<br>";
echo "<b>Temp file:</b> " . $_FILES["file"]["tmp_name"] . "<br>";
?>
Any help would be much appreciated!
UPDATE 1: The var result = exporter.parse(child); is a String and whenever I print this variable to the console it takes a few minutes to load. Would the size of this String be a possible issue with trying to send it to the server?
UPDATE 2: This gets printed to the console after the PHP script has been executed, which makes me think that either nothing is being sent over to the server or the sent data is not being handled correctly by the PHP script.
Image Uploaded Successfully...!!File Name: Type: Size: 0 kBTemp file:
UPDATE 3: Here is a link to the file that I am trying to send.
http://www.filehosting.org/file/details/578744/CleanFemaleOBJ.obj
You can view this file in TextEdit/NotePad to view the String that I want to send. It is pretty much a text file with the .obj extension to convert it to that format so it can be opened in Maya.
UPDATE 4: I have now altered my JavaScript code so that the Blob is appended to the FormData and not the result of reader.readAsDataURL(characterBlob).
//Create OBJ
var exporter = new THREE.OBJExporter();
var result = exporter.parse(child);
//Generate file to send to server
var formData = new FormData();
var characterBlob = new Blob([result], {type: "octet/stream"});
formData.append('file', result);
$.ajax({
url: "ExecuteMaya.php", // Url to which the request is send
type: "POST", // Type of request to be send, called as method
data: formData, // Data sent to server, a set of key/value pairs (i.e. form fields and values)
processData: false, // To send DOMDocument or non processed data file it is set to false
}).done(function(data) {
console.log(data);
});
Using the following code, I was able to upload the .obj file.
I had to increase my maximum upload size for it to work.
You may also think of increasing your maximum execution time as commented below, but I didn't have to.
For simplicity, I put everything in one file called form.php.
form.php
<?php
// good idea to turn on errors during development
error_reporting(E_ALL);
ini_set('display_errors', 1);
// ini_set('max_execution_time', 300);
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
echo "<br/><b>File Name:</b> " . $_FILES["file"]["name"] . "<br>";
echo "<b>Type:</b> " . $_FILES["file"]["type"] . "<br>";
echo "<b>Size:</b> " . ($_FILES["file"]["size"] / 1024) . " kB<br>";
echo "<b>Temp file:</b> " . $_FILES["file"]["tmp_name"] . "<br>";
echo "<b>Error:</b> " . $_FILES["file"]["error"] . "<br>";
$sourcePath = $_FILES['file']['tmp_name']; // Storing source path of the file in a variable
$targetPath = "uploads/" . $_FILES['file']['name']; // Target path where file is to be stored
if (move_uploaded_file($sourcePath, $targetPath)) { // Moving Uploaded file
echo "<span id='success'>Image Uploaded Successfully...!!</span><br/>";
} else {
echo "<span id='success'>Image was not Uploaded</span><br/>";
}
exit;
}
?>
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
</head>
<body>
<form action="form.php" method="post" enctype="multipart/form-data">
<label>File</label>
<input type="file" name="file">
<input type="submit" value="Upload">
</form>
<div></div>
</body>
<script>
$(function () {
$('form').on('submit', function (e) {
e.preventDefault();
// logic
$.ajax({
url: this.action,
type: this.method,
data: new FormData(this), // important
processData: false, // important
contentType: false, // important
success: function (res) {
$('div').html(res);
}
});
});
});
</script>
</html>
So, first test to see if you can upload the .obj file using the code above.
As you are testing it out, have your browser's developer tool open. Monitor your Network/XHR tab [Chrome, Firefox] to see the request that gets made when you click Upload.
If it works, try using the same logic in your original code.
var formData = new FormData();
formData.append('file', result);
$.ajax({
url: "ExecuteMaya.php",
type: "post",
data: formData, // important
processData: false, // important
contentType: false, // important!
success: function (res) {
console.log(res);
}
});
Again, monitor the request made in your Network/XHR tab and look at what is being sent.

Save file in local pc using PHP headers

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...... ;)

Is it possible to save & retrieve the data filled in HTML form to/from xml file stored locally on PC?

I've recently made an HTML form to fill some service reports & now want to save & retrieve them on/from PC itself (preferably in xml format) (not on server).
I'hv checked it on w3scools /on this page too but still I couldn't get the desired solution.
Could you please inform me the possible ways to make it happen.
You can examine the Javascript behind this application (http://www.cloudformatter.com/Nimbus) like this page here:
Sample Nimbus Invoice
This code shows (1) data in the editor area being saved to local storage constantly, (2) option to make a pseudo HTML/XML file and download to disk (Save to ... Disk), (3) option to make that same package and save to storage on the web (New Nimble, Save Nimble). I am not going to go through all the code, the most relevant is here below for saving locally to disk a package stored in the variable "archive":
function SaveFile(archive) {
var textToBLOB = new Blob([archive.innerHTML], { type: 'text/xml' });
var sFileName = 'varypackage.html';
var newLink = document.createElement('a');
newLink.download = sFileName;
if (window.webkitURL !== null) {
newLink.href = window.webkitURL.createObjectURL(textToBLOB);
}
else {
newLink.href = window.URL.createObjectURL(textToBLOB);
newLink.style.display = 'none';
document.body.appendChild(newLink);
}
newLink.click();
}
Look here for all the code (which contains much more that just the saving/loading but it is in here): http://www.cloudformatter.com/Resources/pages/varyhtml/script/02_control.js
If I understand you, you want to store the data on the user's computer, is that right?
Then it would be the best to create an XML file and force download to user's computer.
(I'm using jQuery because it's fastest)
STEP 1: make an ajax request.
function downloadFormData(form){
var formData= $(form).serialize(); //form is an DOM element - the form you want to retrieve data from
$.ajax({
url:"save.php",
data: formData,
success: function (file) {
window.location.href = "download.php?path="+ file
}
});
}
2) Create a php file, name it as save.php with the following content in your root directory:
<?php
$xml_string = "<?xml version etc.?><data>";
foreach($_POST as $key=>$value)
$xml_string.='<'.$key.'>'.$value.'</'.$key.'>';
$xml_string.='</data>
$file = 'formData.xml';
// save to file
file_put_contents('./'.$file, $xml_string);
// return the filename
echo $file; exit;
5) Create a php file, name it as download.php with the following content in your root directory
<?php
$file = 'formData.xml'
// $file = trim($_GET['path']); if you use download.php for anything else
// force user to download the file
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/xml');
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);
unlink($file);
exit;
}
else {
echo "$file not found";
}
I hope you understand the way this works, because you definetly can't leave everything like that (then users could download any file they wanted), but i hope my answer will help you.
EDIT:
a PURE javascript solution
function createXMLandDownload(form){
var a = document.createElement("a");
a.download = "MyXml.xml"; //downloaded file name
a.addEventListener("click" , function (){
var xmlstring = '<?xml version="1.0" encoding="utf-8"?><data>';
$(form).find(":input").each(function(){
xmlstring+="<"+this.name+">"+this.value+"</"+this.name+">";
}
xmlstring+="</data>";
document.open('data:Application/octet-stream,' + encodeURIComponent(xmlstring ));
});
a.click();
}

Need Help Handling a XML HTTP File Upload Request

So, I looked up a tutorial for uploading and sending files to a server with an XML HTTP Request. I followed the tutorial, however, I think I must be missing something. While the file appears to be uploaded and sent, nothing in the "handler" file is ever accessed. Is there a PHP function I need to write to process it? For context, here is what I wrote:
$(document).ready(function()
{
$('#upload-button').click(function(event)
{
$('#upload-button').removeClass("btn-danger");
});
$( "#report-form" ).submit(function( event )
{
var form = document.getElementById('report-form');
var fileSelect = document.getElementById('file-select');
var uploadButton = document.getElementById('upload-button');
event.preventDefault(); // Stop the event from sending the way it usually does.
uploadButton.value = 'Submitting...'; // Change text.
var files = fileSelect.files;
var maxfiles = <?php echo $config['Report_MaxFiles'] ?>;
var mfs = <?php echo $config['Report_MaxFileSize'] ?>;
if(files.length > maxfiles) // Make sure it's not uploading too many.
{
uploadButton.value = 'You uploaded too many files. The limit is ' + maxfiles + '.'; // Update button text.
$('#upload-button').addClass('btn-danger'); // Make the button red, if so.
return;
}
var formData = new FormData(); // Make a "form data" variable.
for (var i = 0; i < files.length; i++) {
var file = files[i];
// Add the file to the request.
if(file.size / 1000 > mfs)
{
uploadButton.value = 'One of the files is too big. The file size limit is ' + (mfs) + 'kb (' + (mfs / 1000) + 'mb).';
$('#upload-button').addClass('btn-danger');
return;
}
formData.append('files[]', file, file.name); // Not really sure what this does, to be honest,
// but I think it makes a file array.
}
var xhr = new XMLHttpRequest(); // Construct an XML HTTP Request
xhr.open('POST', 'assets/class/FileHandler.php', true); // Open a connection with my handler PHP file.
xhr.onload = function ()
{
if (xhr.status === 200)
{
uploadButton.value = 'Files Submitted!'; // NOTE: I do get this message.
}
else
{
uploadButton.value = 'An error occurred.';
$('#upload-button').addClass("btn-danger");
}
};
xhr.send(formData); // I think this is where it dies.
});
});
At the "send(formData)" line, I'm not actually sure if it's sending. Do I set up some sort of listener in FileHandler.php that is activated when the files are sent via XML HTTP request? Or more specifically, how to I save the uploaded files to the server using my FileHandler.php file?
EDIT: I haven't been able to come up with any other PHP code in the FileHandler.php file than this, which I thought might be called when the form is sent (but it isn't):
EDIT 2: Okay, now I have something, but it isn't working (didn't expect it to). I think I may be using the variables wrong:
<?php
$uploaddir = 'data/reports/uploads/' . $_POST['id'] . "/";
$uploadfile = $uploaddir . basename($_FILES['files']['name']);
echo "<script>console.log('RECEIVED');</script>";
echo '<pre>';
if (move_uploaded_file($_FILES['files']['tmp_name'], $uploadfile)) {
echo "File is valid, and was successfully uploaded.\n";
} else {
echo "Possible file upload attack!\n";
}
echo 'Here is some more debugging info:';
print_r($_FILES);
print "</pre>";
It's not saving the file to the directory, nor is it printing the script message. How do I get my report.php file to execute these things in FileHandler.php?
Thanks to the help and patience of #Florian Lefèvre, I got it fixed. :)
The problem was with the path. It wasn't locating the path to the folder data/uploads/ and wasn't making the directory. Here is what I did:
$uploaddir = '../../data/reports/uploads/' . $_POST['id'] . "/";
echo "NAME: " . $_FILES['files']['name'][0] . "\n";
foreach($_FILES['files']['name'] as $filenumber => $filename)
{
$uploadfile = $uploaddir . basename ($filename);
echo "UploadDir " . $uploaddir . "\n";
echo "UploadFile " . $uploadfile . "\n";
echo '<pre>';
echo "MKDir for UploadDir which is: ". $uploaddir . "\n";
mkdir ($uploaddir);
if (move_uploaded_file ($_FILES['files']['tmp_name'][$filenumber], $uploadfile))
{
echo "File is valid, and was successfully uploaded.\n";
}
else
{
echo "Possible file upload attack!\n";
}
echo 'Here is some more debugging info:';
print "</pre>";
}
var_dump ($_FILES);
I haven't gotten rid of some of the debug stuff yet, but that's the general solution.

pass new file name back to jquery

I am using some jquery to help upload a file to a php script. Everything is working fine and the file does in fact get uploaded. But during the upload, I have made it so the file gets resized to our needs, with a new unique file name. I'd like to pass that new unique file name back to the jquery and have it display on the page. Right now, it just displays the original image (which is not resized)
Here's the jquery code:
$(function(){
var btnUpload=$('#upload');
var status=$('#status');
new AjaxUpload(btnUpload, {
action: 'upload-file.php',
name: 'uploadfile',
onSubmit: function(file, ext){
if (! (ext && /^(jpg|png|jpeg|gif)$/.test(ext))){
// extension is not allowed
status.text('Only JPG, PNG or GIF files are allowed');
return false;
}
status.text('Uploading...');
},
onComplete: function(file, response){
//On completion clear the status
status.text('');
//Add uploaded file to list
if(response==="success"){
$('<li></li>').appendTo('#files').html('<img src="./uploads/'+file+'" alt="" /><br />'+file).addClass('success');
} else{
$('<li></li>').appendTo('#files').text(file).addClass('error');
}
}
});
});
And then my upload php file looks like this:
$uploaddir = 'uploads';
$file = $uploaddir . basename($_FILES['uploadfile']['name']);
if (move_uploaded_file($_FILES['uploadfile']['tmp_name'], $file)) {
$path = realpath(dirname(__FILE__));
include $path . '/uploads/phmagick.php';
$temp_file = explode(".", $_FILES['uploadfile']['name']);
$time = time();
$new_file = $time . '.' . $temp_file[1];
$p = new phmagick($path . '/uploads/' . $_FILES['uploadfile']['name'], $path . '/uploads/' . $new_file);
$p->convert();
$phMagick = new phMagick($path . '/uploads/' . $new_file, $path . '/uploads/' . $new_file);
$phMagick->debug=true;
$phMagick->resize(414,414,true);
echo "success";
} else {
echo "error";
}
Any thoughts on how I can get the new unique file name back, which would be something like: 1397413326.jpg?
Thank you
Echo the filename back instead of the word "success".

Categories