I got a page that loads html code from a text file into an textarea and I need to be able to save the contents of it using a script.
I'm using a PHP script to load the code from a file and echo it out to the textarea, but how can I send back the contents to the script and save it either to the same file or to a file with a new name?
I was thinking if getElementById would help me but I'm not sure how.
The load script(it has the ability to delete files too)
// The file hierarchy:
//
//Web root - admin - This file
// - pages - in here are the page text files
// The variable pagesList is the filename chosen in a dropdown list earlier
$page = $_GET["pagesList"];
$action = $_GET["action"];
//get the path to the page( all pages are in a folder named 'pages')
$filename = dirname(dirname(__FILE__))."/pages/".$page;
if(file_exists($filename) and is_file($filename)){
//If I want to load a file
if($action == "open"){
$f = fopen($filename,"rt");
$content = fread($f, filesize($filename));
echo $content;
#fclose($f);
//If I want to delete a file
}elseif($action == "delete" && is_file($filename)){
//move the working directory to where the file is
$old = getcwd();
chdir(dirname(dirname(__FILE__))."/pages/");
//----
if(unlink($filename))
echo "File deleted,".$filename;
else
echo "Error deleting file!";
//change back the working directory to where it was
chdir($old);
//If I want to save a file
}elseif($action == "save"){
if(file_exists($filename)){
//Unknown script, need help!
}else{
}
}
}
The textarea is only one line with an include in it:
<textarea id="html_content" style="width:600;height:200;"><?php include("loader.php") ?></textarea>
To sum it up: I need help getting the contents of an textarea to a script for saving later.
EDIT: Thanks to davidkonrad I just had to add a few POST receives in the script and add file_put_content with the content sent to it.
The problem that arised is that jQuery apparently puts \ before each " or '. That messes up all the html code that is supposed to be clean and valid. I'll have to replace the \" with " somehow, str_replace wont cut it. Any ideas?
EDIT2: Thanks again to davidkonrad that fixed it by using encodeURIComponent(jQuery) clientside and urldecode(PHP) serverside.
Update, OK if you just are in doubt how to submit a textarea to your loader.php :
<form method="post" action="loader.php">
<input type="hidden" name="filename" value="test.html">
<input type="hidden" name="action" value="save">
<textarea name="html_content"></textarea>
<input type="submit" value="save">
</form>
loader.php, now you have
$filename=$_POST['filename'];
$action=$_POST['action'];
$html_content=$_POST['html_content'];
Which here is "test.html", "save" and any text typed into the textarea. use those variables in your if .. else loop as above, eg
} elseif($action == "save"){
if(file_exists($filename)){
//Unknown script, need help!
file_put_contents($filename, $html_content); //or how you want to do it
}
}
The disadvantages is
the page needs to be reloaded on each action
you need to echo the inserted content again, between <textarea> .. </textarea> once it is inserted (as I understand, the HTML is part of loader.php)
likewise keeping track of the current filename is more complicated
NB : Unless there is a particular reason, you dont have to check if a file already exists before writing to it. And still thinks travelling around in the directories just makes it complicated :) Is /pages/ not just a relative path?
It does not need to be so complicated. I would use a more simple and structured approach, consisting of
A PHP class that performs each task by simple file_put_contents, file_get_contents and unlink, including some small error handling
A system of $.ajax calls (jQuery) calling the above PHP class
The following working example performs save, load and delete of HTML files to a directoty /files, which you must give RW permissions.
file.php
class File {
private $filename;
private $dir = 'files/';
public function __construct() {
$action = isset($_POST['action']) ? $_POST['action'] : false;
$this->filename = isset($_POST['filename']) ? $_POST['filename'] : false;
if ((!$action) || (!$this->filename)) return;
switch ($action) {
case 'save' :
$this->save(); break;
case 'load' :
$this->load(); break;
case 'delete' :
$this->delete(); break;
default :
return;
break;
}
}
private function save() {
$content = isset($_POST['content']) ? $_POST['content'] : '';
file_put_contents($this->dir.$this->filename, urldecode($content));
}
private function load() {
$content = #file_get_contents($this->dir.$this->filename);
echo $content;
}
private function delete() {
unlink($this->dir.$this->filename);
}
}
$file = new File();
file.html, markup
<input type="text" id="filename" value="test.txt"><br>
<textarea id="html_content" style="width:600;height:200;"></textarea>
<br>
<button id="save">save</button>
<button id="load">load</button>
<button id="delete">delete</button>
file.html, script :
var url = 'file.php';
$("#save").click(function() {
$.ajax({
url : url,
type: 'post',
data : {
filename : $("#filename").val(),
action : 'save',
content : encodeURIComponent($('#html_content').val())
}
});
});
$("#delete").click(function() {
$.ajax({
url : url,
type: 'post',
data : {
filename : $("#filename").val(),
action : 'delete'
}
});
});
$("#load").click( function() {
$.ajax({
url : url,
type: 'post',
data : {
filename : $("#filename").val(),
action : 'load'
},
success : function(html) {
$("#html_content").val(html);
}
});
});
The HTML content (tags, HTML entities) is maintained upon save by the use of encodeURIComponent and urldecode. Try it out yourself, and consider this as the base for a more complex system. If you want to create a new file, just enter a new filename in the filename box. If you want to load a file, enter that filename in the filename box. I think file_put_contents etc is by far more robust than dealing with file handles, chdir(dirname(dirname(__FILE__))."/pages/"); (??) and so on.
try using php fputs function to save file
Related
I would like to access a file after it was uploaded to the server via dropzone.js (v5) and PHP, i.e. I'd like to retrieve the file URL. How can I get it?
form.php:
<form action="upload.php" class="dropzone" enctype="multipart/form-data">
<div class="fallback">
<input name="file" type="file" multiple />
</div>
</form>
<script src="/js/dropzone.js"></script>
<script>
Dropzone.autoDiscover = false;
$('.dropzone').dropzone({
init: function () {
this.on("complete", function (file) {
runthisfunction();
}) // end on complete
}
});
</script>
upload.php:
<?php
if (!empty($_FILES)) {
$random = randomString(18);
$tempFile = $_FILES['file']['tmp_name'];
$name = $_FILES['file']['name'];
$fileExt = strtolower(substr(basename($name), strrpos(basename($name), ".") + 1));
$newname = $random.'.'.$fileExt;
move_uploaded_file($tempFile,"images/$newname");
} // end if files not empty
?>
I have tried retrieving the uploaded file URL via the file object, but no success:
this.on("complete", function (file) {
console.log(file);
console.log(file.dataURL);
console.log(file.name);
}) // end on complete
Since the file is uploaded with PHP and renamed within the upload.php, I believe I would need to "POST" this filename somehow to another file and then retrieve it back. How can I do that?
Your intuition about needing to get the filename back from the server is correct. There's a simple example in the Dropzone FAQ which shows the basic idea.
1) Your server has to respond to the upload POST with the details of where it put the file - eg URL, filename, path, etc. So in your case, at the end of your PHP code, you'd need to do something like:
// ... rest of your PHP ...
move_uploaded_file($tempFile,"images/$newname");
// Let the browser/JS know we are sending a JSON response back. Make sure there
// is no output before this.
header('Content-type: application/json');
echo json_encode([
'status' => 'OK', // Not required, but maybe useful
'image' => "images/$newname",
]);
2) In your JS, you need to accept that response from the server, and do something with it. The Dropzone docs show for the success event:
The file has been uploaded successfully. Gets the server response as second argument.
This sounds like the one we need. So replace your complete handler with one for success, and add a 2nd argument:
this.on("success", function (file, response) {
console.dir(response);
// response.image will be the relative path to your uploaded image.
// You could also use response.status to check everything went OK,
// maybe show an error msg from the server if not.
});
The Dropzone FAQ item I linked to above shows using an .emit() method to display the image, I'm not familiar with that and it doesn't seem to be described in the docs. Try it, maybe that works and suits your needs. If not, you could do something like:
// Maybe you have an <img class='thumbnail'> in your HTML, ready to show the upload
$('.thumbnail').attr('src', response.image).fadeIn();
I have read a number of solutions here and elsewhere that show how a upload a file to an Azure Blob storage. I have the php code working below when the file is hard coded (followed the MS tutorial), but not if I try to post the file to the PHP (get error: not a valid path). I want a user to be able to browse to a file in the form and submit (then return the url so that I can use it for other actions). I read on SO that javascript shows a fake path for security, and I assume that is my issue. How, then, do I get the proper path to the PHP file if I cannot post it. I have tried a default post and an ajax attempt. Is there a solution?
My PHP (works when the file is hard coded):
require_once 'WindowsAzure\WindowsAzure.php';
use WindowsAzure\Common\ServicesBuilder;
use WindowsAzure\Common\ServiceException;
$connectionString = "DefaultEndpointsProtocol=https;AccountName=myaccount;AccountKey=mykey";
// Create blob REST proxy.
$blobRestProxy = ServicesBuilder::getInstance()->createBlobService($connectionString);
//$content = fopen("c:\myfile.txt", "r"); //this works when hard coded like this
//$blob_name = "myblob.txt";
//get posts
//$fpath = $_POST["resFile"];//tried this too - no go
$fpath = $_FILES["resFile"];
$fname = "hello.txt";
$content = fopen($fpath, "r"); //I know this isn't right, but trying
$blob_name = $fname;
try {
//Upload blob
$blobRestProxy->createBlockBlob("saskcontainer", $blob_name, $content);
}
catch(ServiceException $e){
// Handle exception based on error codes and messages.
// Error codes and messages are here:
// http://msdn.microsoft.com/en-us/library/windowsazure/dd179439.aspx
$code = $e->getCode();
$error_message = $e->getMessage();
echo $code.": ".$error_message."<br />";
}
//and I need to return the url here on success
here is the HTML and JS:
<form action="test.php" method="post" enctype="multipart/form-data">
<div data-role='page' id="resFileCont" >
<input type="file" name="resFile" id="resFile" value="" />
<!--<input type="text" name="name" />-->
<input type="submit" value="Submit" data-inline="true"/>
</div></form>
<div id="res"></div>
<script>
$(document).ready(function () {
$("form").on('submit', (function (e) {
e.preventDefault();
$.ajax({
url: "test.php", // Url to which the request is send
type: "POST", // Type of request to be send, called as method
data: new FormData(this), // Data sent to server, a set of key/value pairs (i.e. form fields and values)
contentType: false, // The content type used when sending data to the server.
cache: false, // To unable request pages to be cached
processData: false, // To send DOMDocument or non processed data file it is set to false
success: function (data) // A function to be called if request succeeds
{
alert(data)
$("#res").html(data)
}
});
}));
});
</script>
Just replaced
$content = fopen($fpath, "r");
with
$content = fopen($_FILES["resFile"]["tmp_name"], 'r');
I have a page that allows users to upload multiple files and preview them without refreshing the page using jquery. In php I generate a unique file_id for each filename which I would then like to pass back in to JQuery and use it to load up the preview image etc.
I hope I have explained myself clearly.
Thanks for any pointers!
The PHP code:
// php code to upload file and generate unique file id. then...
if (move_uploaded_file($main_image, $file)) {
echo "success";
echo $file_id; // <--- I WANT TO PASS THIS VARIABLE BACK IN TO JQUERY
} else {
echo "error";
}
The J Query Code:
$(function(){
var btnUpload=$('#upload_main');
var mestatus=$('#mestatus');
var button=$('#button');
var files=$('#main_file');
new AjaxUpload(btnUpload, {
action: 'classified-ads/upload-classified-image.php?filenumber=1',
name: 'file1',
onSubmit: function(file, ext){
if (! (ext && /^(jpg|png|jpeg|gif|'')$/.test(ext))){
// extension is not allowed
mestatus.text('Only JPG, PNG or GIF files are allowed');
return false;
}
mestatus.html('<img src="extras/ajaxuploader/progress_bar.gif" height="30" width="340">');
button.html('Loading...');
$('#upload_main').removeClass('hover').addClass('upload_button_loading');
},
onComplete: function(file, response){
//On completion clear the status
mestatus.text('Photo Uploaded Sucessfully!');
button.html('Change Photo');
$('#upload_main').removeClass('upload_button_loading').addClass('upload_button');
//On completion clear the status
files.html('');
//Add uploaded file to list
if(response==="success"){
var file2 = file.replace(/\s/g, "_");
var file_id= file_id;
$('<div></div>').appendTo('#main_file').css('background-image', "url(/ht/classified-ads/temp_images/prev1_<?php echo $parsed_user;?>_"+file_id+")").addClass('main_success');
$("#image1_temp").val("main1_<?php echo $parsed_user;?>_"+file_id+"");
$("#thumbnail_temp").val("thumbnail_<?php echo $parsed_user;?>_"+file_id+"");
} else{
$('<li></li>').appendTo('#main_file').text(file).addClass('error');
}
}
});
});
In your PHP:
$response = array('result' => 'success', 'file_id' => $file_id);
echo json_encode($response);
In your jQuery:
var obj = $.parseJSON(response);
You would then check whether the response was a success with if (obj.result == 'success') and you'd get your file_id with obj.file_id
The simplest way is to do this allowing for MULTIPLE values to be returned:
// Make a variable to hold data to send back and keep track of your separator
$data = '';
$separator = 1;
// Put this in a loop, your loop will depend on how many file uploads you have
// I did not do the loop for you
if (move_uploaded_file($main_image, $file)) {
// echo "success"; Take this out
if ($separater==1){
$data .= $file_id;
} else {
$data .= ','.$file_id;
}
$separater++;
}
// Now outside the loop echo the results back
echo $data;
With this info echoed back you can manipulate it with Javascript (Jquery). Just use something like spli(','); which gives you an array of the file names you needed.
If you only want one value to come back, meaning you only have one file id to send back foregt everything about the loop and the PHP would be this:
if (move_uploaded_file($main_image, $file)) {
// echo "success"; Take this out
$data = $file_id;
// Now echo the results back
// Its been a while since I've done this but there may be times its ok to use return
echo $data;
} else {
// Handel error here
echo "error";
}
Now based off your code this echoed information should be picked up and processed here:
onComplete: function(file, response){ ... }
Instead of looking for "Success" you need to change your code to look for a file id or something like error instead (which is easier) like so:
if(response!=="error"){
// Now you can use your variable "response" here since it contains the file id
} else {
// Handle the error
}
The reason I gave you a long explanation about getting multiple values back is because that is more common as you start making more advanced forms and it wouldn't hurt to use now. This way you can allow multiple file uploads for example. What I do for example when using AJAX is echo back something like this:
1::value,value,value
Now I just split that into arrays first by :: and then by , this line for example says No Error Happened (1 which as we know is also TRUE) and here is your data: value,value,value which you can now use for things in your Jquery or just print to the document.
You should look at the Jquery AJAX page for in depth examples and explanations, it explains the trouble you ran into getting results back. Look at .done .success .complete especially.
I have seen many topics about this problem but none of them got a legit answer or a including PHP file.
I want to make a drag & drop saving tool. The problem is that my files are not getting uploaded to my ftp folder.
I got the following code:
HTML:
<div id="drop_zone">
<p>Drop Here</p>
</div>
<form enctype="multipart/form-data" id="yourregularuploadformId">
<input type="file" name="files[]" multiple="multiple">
</form>
JS:
$(function() {
var dropZone = document.getElementById('drop_zone');
dropZone.addEventListener('dragover', handleDragOver, false);
dropZone.addEventListener('drop', handleFileSelect, false);
etc.... dropping part
function handleFileSelect(evt) {
evt.stopPropagation();
evt.preventDefault();
files = evt.dataTransfer.files;
uploadFile(files);
etc... getting file to my method
function uploadFile(droppedFiles){
// add your files to the regular upload form
var uploadFormData = new FormData($("#yourregularuploadformId")[0]);
if(droppedFiles.length > 0) { // checks if any files were dropped
for(f = 0; f < droppedFiles.length; f++) { // for-loop for each file dropped
uploadFormData.append("files[]",droppedFiles[f]); // adding every file to the form so you could upload multiple files
}
}
// the final ajax call
alert(uploadFormData);
$.ajax({
url : "php/uploadFile.php", // use your target
type : "POST",
data : uploadFormData,
cache : false,
contentType : false,
processData : false,
success : function(ret) {
alert(ret);
}
});
}
Got the above code from another topic. (alert(uploadFormData); -> gives me a Formdata aboject)
PHP:
move_uploaded_file($_FILES["file"]["tmp_name"],
"ftp/" . $_FILES["file"]["name"]);
echo "Stored in: " . "upload/" . $_FILES["file"]["name"];
Can't make it work :<
The message i get from the callback function in my JS is:
Undefined index: file
Your PHP code needs to iterate over all of the files in the request. Based on your javascript, your PHP code should look something like this:
foreach ($_FILES["files"] as $file) {
move_uploaded_file($file['tmp_name'], $target);
}
The $target variable must point at the local destination for your file. See the PHP manual for more details.
I have a page with a WYSIWYG editor the user can use. After editing, they can press a button, and the javascript should POST the current page to a save.php file and refresh the page with new information.
There are two problems. The first is that initially the page doesn't load with the updated file. The user has to refresh the page to see it updated (maybe it just takes an extra second to write the file?). The second problem, is that after the first time the temporary file was created, it cannot be overwritten, so the page never updates after the first refresh. Here are the snippets I'm working with:
Javascript function on the WYSIWYG editor page (editor.php):
function refresh(html,username,info)
{
$.post("save.php", { html: html, username: username } );
window.location = 'editor.php?info=' + info;
}
save.php file
$html = $_POST['html'];
$username = $_POST['username'];
file_put_contents('temp/' . $username . '.txt', $html);
As the browser may not have issued the POST request before navigating to the next page, use the success callback from the post to do the relocate:
function refresh(html,username,info) {
$.post("save.php", { html: html, username: username }, function() {
window.location = 'editor.php?info=' + info;
});
}
As other people have already commented, using data directly from a form post without sanitising it is a really bad plan and opens your server up to all kinds of malicious attacks. Have a look at some of these questions: https://stackoverflow.com/search?q=sanitize+php
If the data is getting to your server ok, make sure that the access permissions on the directory 'temp' allow write access from the web server user (if you have access to SSH to your server, run chmod go+w /path/to/temp, otherwise most FTP programs allow you to set file permissions too).
why not use fopen and fwrite?
simply use:
$html = $_POST['html'];
$username = $_POST['username'];
$file = "temp/" . $username . ".txt";
if (!file_exists($file)) {
$files = fopen($file, "x+");
} else {
$files = fopen($file, "w+");
}
if(fwrite($files, $html)) {
echo "Success!";
} else {
echo "Failure!";
}
for the php and to make the refresh work in js, try putting the statement in the success function like this:
function refresh(html,username,info) {
$.post("save.php", { html: html, username: username },
function (response) {
window.location = 'editor.php?info=' + info;
console.log(response);// for debugging :)
});
}
The ajax request is asynchrone so the writing operation can be in progress when the redirection is started. You have to listen to the finished exent of the $.post action to do the redirect.