I've simplified my code for uploading a file without iFrame or flash engine, and i came up to this ajax function:
<input type="file" name="uploadfile" id="myfile" /><label for="file" id="progress"></label>
<script src="js/jquery-1.7.1.min.js"></script>
<script>
function uploadFile(files) {
var xmlhttp;
if(window.XMLHttpRequest)
xmlhttp = new XMLHttpRequest();
else
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
xmlhttp.upload.onprogress = function(e) {
$("#progress").empty().append(e.loaded + " - " + e.total);
}
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
alert(xmlhttp.responseText + "DONE!");
}
}
xmlhttp.open("post", "post.php", true);
xmlhttp.setRequestHeader("If-Modified-Since", "Mon, 26 Jul 1997 05:00:00 GMT");
xmlhttp.setRequestHeader("Cache-Control", "no-cache");
xmlhttp.setRequestHeader("X-Requested-With", "XMLHttpRequest");
xmlhttp.setRequestHeader("X-File-Name", files[0].fileName);
xmlhttp.setRequestHeader("Content-Type", "multipart/form-data");
xmlhttp.send(files[0]);
}
$(document).ready(function() {
$("#myfile").change(function() {
uploadFile(this.files);
});
});
</script>
This is the php code which reply to the ajax function:
<?php
if(isset(
$_SERVER['CONTENT_TYPE'],
$_SERVER['CONTENT_LENGTH'],
$_SERVER['HTTP_X_FILE_NAME']
) &&
$_SERVER['CONTENT_TYPE'] == 'multipart/form-data'){
$file->name = basename($_SERVER['HTTP_X_FILE_NAME']);
$input = fopen('php://input', 'rb');
$file = fopen('files/'.$file->name, 'wb');
stream_copy_to_stream($input, $file);
fclose($input);
fclose($file);
} else {
echo "Error";
}
?>
The problem is, sometimes it works sometimes it bugs up while trying to upload the same file. I hope there is a solution to fix this issue. The code is simple, when i choose a file with input file type, the uploadFile function executes.
When it bugs out, i can see the file starting to be uploaded but it doesnt have the original size, so somewhere it could bug and stop uploading.
Thank you in advance, Daniel!
I'm not sure it is your problem, but you should anyway make sure your server allows for uploading large enough files and can handle them without timing out.
You can set this in code or php.ini (example in code:)
ini_set('memory_limit', '96M');
ini_set('post_max_size', '64M');
ini_set('upload_max_filesize', '64M');
Then, make sure your server does not time out:
$seconds=120;
set_time_limit ( $seconds );
All this code coes on the top of your PHP file.
Related
I am following a tutorial on W3Schools for AJAX PHP. https://www.w3schools.com/php/php_ajax_php.asp
Here is the twist: I am doing this in wordpress. The following is a method that DOES work, but it is less than ideal.
1) Create the following gethint.php in the root directory.
<?php
// Array with names
$a[] = "Anna";
$a[] = "Brittany";
...
$a[] = "Vicky";
// get the q parameter from URL
$q = $_REQUEST["q"];
$hint = "";
// lookup all hints from array if $q is different from ""
if ($q !== "") {
$q = strtolower($q);
$len=strlen($q);
foreach($a as $name) {
if (stristr($q, substr($name, 0, $len))) {
if ($hint === "") {
$hint = $name;
} else {
$hint .= ", $name";
}
}
}
}
// Output "no suggestion" if no hint was found or output correct values
echo $hint === "" ? "no suggestion" : $hint;
2) Using the CSS & Javascript toolbox plugin, add this code to the header:
<script>
function showHint(str) {
if (str.length == 0) {
document.getElementById("txtHint").innerHTML = "";
return;
} else {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("txtHint").innerHTML = this.responseText;
}
};
xmlhttp.open("GET", "/gethint.php?q=" + str, true);
xmlhttp.send();
}
}
</script>
3) Create a page with the following code (in plain text):
<p><b>Start typing a name in the input field below:</b></p>
<form>
First name: <input type="text" onkeyup="showHint(this.value)">
</form>
<p>Suggestions: <span id="txtHint"></span></p>
While this works, having to create a php file and adding to the root directory seems like bad practice. It would be better to have this php file stored in the plugins directory. However that causes this line of the header script to fail as 404:
xmlhttp.open("GET", "/gethint.php?q=" + str, true);
Simply changing the relative path won't work, because theoretically, different users can have their plugin folder in different locations.
I figure I should be using the wp_ajax_ and wp_ajax_nopriv_ hooks, but my attempts I have failed, so I am probably doing it wrong. Please help.
Doing ajax in WordPress should all be sent to /wp-admin/admin-ajax.php,
to do that, in your plugin's main file or the index.php file,
register your ajax action like this:
// let's do the ajax thing here
add_action( 'wp_ajax_theNameOfMyCustomAjax', 'theFunctionThatMyAjaxWillCall' );
function theFunctionThatMyAjaxWillCall() {
// include your ajax file here, in this case
// I assumed that we placed the gethint.php in
// /wp-content/plugins/yourpluginname/gethint.php
include( plugin_dir_path( __FILE__ ).'gethint.php' );
// don't forget to add "die;" every time you return a response to your ajax
//Example: echo $hint ?? "no suggestion"; die;
// or you can add the termination code right here
die; // this will prevent the ajax response to have 0 in the end.
}
Now, in your javascript, instead of calling the filename of your ajax file, you can now use the global ajaxurl javascript variable like this:
xmlhttp.open("GET", ajaxurl+"?action=theNameOfMyCustomAjax&q=" + str, true);
I am having issues saving images to local file. Every other things look fine but the image won't just save. Here is a snippet of my code.
function saveImage(){
var xmlhttp;
xmlhttp=((window.XMLHttpRequest)?new XMLHttpRequest():new ActiveXObject("Microsoft.XMLHTTP"));
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
//do something with the response
}
}
xmlhttp.open("POST","ajxstuff.php",true);
var oldCanvas = document.getElementById('cvs').toDataURL("image/png");
var img = new Image();
img.src = oldCanvas;
xmlhttp.setRequestHeader("Content-type", "application/upload")
xmlhttp.send(oldCanvas);
}
Here is the the ajxstuff.php
<?php
if (isset($GLOBALS["HTTP_RAW_POST_DATA"]))
{
// Get the data like you would with traditional post
$rawImage=$GLOBALS['HTTP_RAW_POST_DATA'];
// Remove the headers
$removeHeaders=substr($rawImage, strpos($rawImage, ",")+1);
// decode it from base 64 and into image data only
$decode=base64_decode($removeHeaders);
// save to your server
$saveName = 'C:\Users\Administrator\Downloads\image009.png';
$fopen = fopen($saveName, 'wb' );
fwrite( $fopen, $decode);
fclose( $fopen );
}
?>
OK, here's my revised answer: You could instead of sending the image as (what looks like) a file, send it as text - since that's what you get from toDataUrl() (a base64 encoded representation of the image).
$.post('ajxstuff.php',{
myChart: document.getElementById('cvs').toDataURL()
}, function ()
{
/* callback */
})
And in your PHP script the data would show up in $_POST['myChart'] - and you could write it to a file like this:
<?php
$data = base64_decode($_POST['myChart']);
file_put_contents('C:\Users\Administrator\Downloads\image009.png', $data);
?>
I need help with creating a progress bar for my php upload site. I've got the upload and exctract part sorted but i need help with the progress bar. I'm not sure how to do it. Also, is there a maximum file size for the upload?
HTML
<?php if($message) echo "<p>$message</p>"; ?>
<form enctype="multipart/form-data" method="post" action="">
<label>Choose file (.zip): <input type="file" name="zip_file" /></label>
<br />
<input type="submit" value="Upload" name="submit" value="Upload" />
</form>
PHP
<?php
if($_FILES["zip_file"]["name"]) {
$filename = $_FILES["zip_file"]["name"];
$source = $_FILES["zip_file"]["tmp_name"];
$type = $_FILES["zip_file"]["type"];
$name = explode(".", $filename);
$accepted_types = array(
'application/zip',
'application/x-zip-compressed',
'multipart/x-zip',
'application/x-compressed');
foreach($accepted_types as $mime_type) {
if($mime_type == $type) {
$okay = true;
break;
}
}
$continue = strtolower($name[1]) == 'zip' ? true : false;
if(!$continue) {
$message = "[...] not a .zip file. Please try again.";
}
$target_path = "./".$filename;
if(move_uploaded_file($source, $target_path)) {
$zip = new ZipArchive();
$x = $zip->open($target_path);
if ($x === true) {
$zip->extractTo("./");
$zip->close();
unlink($target_path);
}
$message = "Your .zip file was uploaded and unpacked.";
} else {
$message = "There was a problem with the upload. Please try again.";
}
}
?>
You can make some changes to fit but this works rather well if you want a progress bar. You can add more eventlisteners and make it how you want. I hope this is a good starting point for you.
function uploadFile(){
var file = document.getElementById("zip_file").files[0];
var formdata = new FormData();
formdata.append("zip_file", file);
var ajax = new XMLHttpRequest();
ajax.upload.addEventListener("progress", function(event) { runprogress(event); } , false);
ajax.addEventListener("load", function(event) {uploadcomplete(event); }, false);
//Target your php file.
ajax.open("POST", "upload.php");
ajax.send(formdata);
}
function runprogress(event){
//The progress %, you might want to Math.round(percent)
var percent = (event.loaded / event.total) * 100;
}
function uploadcomplete(event){
//This will = to your php reply.
var AjaxReply=event.target.responseText;
}
As far as I know you would have to use JavaScript to do this. Post your data through an AJAX call and initialize the progress bar. Over time animating it so that the bar "fills up".
Eventually the AJAX call will complete and will send a response back, upon the completion of the call you can finish the animation. This is how I would assume most progress bars work as they typically go up then stop around 99% until the post returns it's "complete status".
In any case, you would have a progress bar, represented by a <div> for example, with a width that would increase as time goes on, or a number would go up etc... and you would animate this using JavaScript and/or jQuery. Hopefully this will get you started in the right direction.
EDIT
Here's a link to a tutorial describing the steps necessary to upload files to the server using AJAX: Uploading Files with AJAX
We successfully set up image uploading on our server with nginx. Everything gets posted to /upload and then redirects to /file for processing. The file gets uploaded and stored, but there are headers at the top of the file.
------WebKitFormBoundaryqUwBABts5uiLHgDN
Content-Disposition: form-data; name="picture"; filename="coldplay.jpg"
Content-Type: image/jpeg
What am I to do with this? Do I strip these headers out with PHP and then save the file again?
Is uploading files with these headers expected behavior?
Here is the form:
<form action="/upload/" id="upload3" method="post">
<input type="file" id="file" name="picture" value=""/>
<input type="submit" onclick="return uploadFiles(this.form);">
</form>
and js:
<script type="text/javascript">
function uploadFiles(form) {
var formData = new FormData(form);
var url = "/upload/";
var xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.onload = function(e) {
if (this.status == 200) {
console.log(this.responseText);
}
};
xhr.send(formData); // multipart/form-data
return false;
}
</script>
I'm using these lines of code to strip the first four lines from our uploaded image files. I found it somewhere on SO and it works great -- unfortunately I don't know where it was.
$line_to_strip = 4;
$new_file = new SplFileObject($file_full_new, 'w');
foreach (new LimitIterator(new SplFileObject($file_full), $line_to_strip) as $line)
$new_file->fwrite($line);
I don't know if this is our permanent solution, however.
I'm using lighttpd + PHP 5.4 running with FastCGI on buildroot embedded linux.
I have written some time ago a modified version of PHP file upload progress script using following tutorial: http://phpmaster.com/tracking-upload-progress-with-php-and-javascript/
I was previously working on Slackware Apache with mod_php and everything worked fine.
Unfortunately, the script is not working. I have made sure that in php.ini session.upload_progress = On and sessions are enabled. I have verified that sessions are working in general by using two simple php files as in 4. post here http://quirm.net/forum/topic.php?id=3950.
The script is supposed to show loading screen and percentage of file upload. It is achieved by sending progress.php requests every 0.2 second. Unfortunately, no matter how large is the file (I use ~13 MB files for testing, I have ensured that the file upload size in php.ini accepts this size) the upload ends after first request because it returns 100. I have debbuged progress.php and it looks that the whole $_SESSION variable is empty.
Here is my form HTML code:
<form enctype="multipart/form-data" action="actions/upload_upgrade.php" method="post" target="hidden_iframe" onsubmit="upload_type='config'; startUpload('config_form')" id="config_form">
<p class="stdtext">
Select File:
<input type="hidden" name="type" value="config">
<input type="hidden" value="config_form"
name="<?php echo ini_get("session.upload_progress.name"); ?>">
<input type="file" size="35" name="userfile" />
<br><br>
<input type="submit" class="defaultbtn" name="Upload" value="Upload" onclick="showLoadingScreen(true)"/>
</p>
</form>
My Javascript code (please note that upload and response handling functions are made universal because they accept uploads from several different forms that are used to upload configuration, firmware etc.).
function sendUploadRequest(form_name)
{
job_name="Upload";
var http = createRequestObject();
http.open("GET", "actions/progress.php?form_name="+form_name);
http.onreadystatechange = function () { handleResponse(http,"sendUploadRequest('"+form_name+"')"); };
http.send(null);
}
function startUpload(form_name)
{
showLoadingScreen(true);
postDataSync("actions/uw.php");
document.getElementById("loadingtext").innerHTML="Uploading file...";
setTimeout("sendUploadRequest('"+form_name+"')", 200);
}
function handleResponse(http,fun_name)
{
hideInfo();
var response;
if (http.readyState == 4)
{
response = http.responseText;
document.getElementById("loadingtext").innerHTML = response + "%";
if (response < 100)
{
setTimeout(fun_name, 200);
}
else
{
showLoadingScreen(false);
if(job_name=="")
printInfo("Job completed successfuly");
else
{
if(job_name=="Upload"&&upload_type=="config")
{
if(hidden_iframe.window.document.body.innerHTML=="SUCCESS")
{
printInfo(job_name+" completed successfuly");
showLoadingScreen(true);
document.getElementById("loadingtext").innerHTML="Restoring backup...";
var result=postDataSync("actions/extract_backup.php");
showLoadingScreen(false);
if(result.substring(0,5)=="ERROR")
{
printError("Error while extracting backup configuration:<br><br>"+result.substring(6));
}
else if(result.substring(0,7)=="SUCCESS")
{
printInfo("Backup configuration restored successfully");
}
else
{
printError("Unknown error while extracting backup. Please contact service.");
}
}
else
{
printInfo(job_name+" was not completed because of errors");
}
}
else
{
if(hidden_iframe.window.document.body.innerHTML=="SUCCESS")
printInfo(job_name+" completed successfuly");
else
printError(job_name+" was not completed because of errors");
}
}
}
}
}
function createRequestObject()
{
var http;
if (navigator.appName == "Microsoft Internet Explorer")
{
http = new ActiveXObject("Microsoft.XMLHTTP");
}
else
{
http = new XMLHttpRequest();
}
return http;
}
And my PHP code progress.php:
<?php
session_start();
//print_r($_SESSION);
$key = ini_get("session.upload_progress.prefix") . $_GET['form_name'];
if (!empty($_SESSION[$key])) {
$current = $_SESSION[$key]["bytes_processed"];
$total = $_SESSION[$key]["content_length"];
echo $current < $total ? ceil($current / $total * 100) : 100;
}
else {
echo 100;
}
On http://de3.php.net/manual/de/session.upload-progress.php it's said: "Note, this feature doesn't work, when your webserver is runnig PHP via FastCGI."