Dropzone check max. files PHP side - javascript

I'm sending some files through the dropzone.js to my PHP server. I'm having a problem validating the max files being sent PHP side. Even though I will use the maxFiles param for dropzone.js I would like to make sure nothing odd is being sent more times than needed. The main problem is that dropzone can send the file per POST request, so I cannot simply count($_FILES) because there is always gonna be 1.
So I decided to store the temporary uploads in the database using the session id and the field hash and select the count of uploads by that hash.
Unfortunately, that doesn't work as intended, since another request is being sent too fast.
Code is:
if ($request->ajax())
{
$hash = md5(Session::getId() . '_myupload');
$count = DB::query("SELECT COUNT(id) FROM temp_uploads WHERE hash = ?")->param($hash)->execute();
echo $count; // 0
// Store the file
DB::query("INSERT INTO temp_uploads (key) VALUES (?)")->param($hash)->execute();
$request->file('myupload')->store('uploads');
}
I'm uploading two files and the second request is being sent before the INSERT query even finished executing.
How can I properly validate the max files from multiple request in PHP?

Related

Save variable to text file serverside using jquery

I am trying to save a variable for counting the views of my personal website, I dont need to use php because its literally a viewcount. I know how to retrieve the count from the server using $.post, but how would I retrieve it (Edit: In the simplest way possible.)?
The website I'm trying to do it with is http://artsicleprojects.com/
Thanks in advance!
You will need PHP for this question, because it is dealing with server-side actions. First, you need to make a server-side script to increment the text file's number. Then, you will need to make a client-side script to make a request to the server. This script increments a number in the text file every time the request is made. Anyway, here's how I would do it (Note: this code is un-tested):
PHP:
<?php
/*Reads and collects current count.*/
$rfile = fopen("views.txt", "r") or die("Unable to open file!");
$count = fread($rfile,filesize("views.txt"));
fclose($rfile);
/*Increments the count.*/
$wfile = fopen("views.txt", "w");
$ncount = $count + 1;
fwrite($wfile, $ncount);
fclose($wfile);
?>
Note on code: for this code to work correctly, you may need a text file already made (views.txt), in the same directory as the PHP script, with a single "0" written in it.
JavaScript (with jQuery):
$.post("phpscript.php", function(data, status){
console.log(status);
});
This also is supposed to be in the same directory as the script to work.

Storing information from php script

I m working on an html page that contains a form allowing users to enter their informations and upload files. all informations will be inserted in Mysql database.
in Javascript, im using XMLHttpRequest to send the files to the server and "upload.php" to rename (to avoid dupplicated names) and move them in the upload directory.
For better user experience, this will be done before submitting the whole form.
My question is : How can i store the new filenames (defined in upload.php)to use them in the form submission "submit.php"?
the reason for this is that in "submit.php", i insert first the user informations in "user" table and then select the "user_id" (auto increment) that will be inserted with filenames in the "files" table.
Could php sessions be an approach to do this ? is there another way? Thanks for your help
html:
<form action="submit.php" method="post" id="submitform">
<div>
<--!user info part1-->
</div>
<div id="filesContainer" class="eltContainer">
<input type="file" id="filesList" multiple>
</div>
<div>
<--!user info part2-->
</div>
javascript:
var fd = new FormData()
var xhr = new XMLHttpRequest()
for (var i=0,nb = fichiers.length; i<nb; i++) {
var fichier = fichiers[i]
fd.append(fichier.name,fichier)
}
xhr.open('POST', 'upload.php', true)
upload.php :
<?php
foreach($_FILES as $file){
$filename = date('Y') . date('m') . date('d') . date('H') . date('i') . basename($_FILES[$file]['name']);
move_uploaded_file( $file['tmp_name'],"../upload_dir/" .$filename);
}
exit;
I would consider using something like md5 for unique filenames.
Nevertheless you can push filenames into some array, and than return those filenames, as a result of post request, and put them back into some input field.
To retrieve the response simply add this lines to your code below open
xhr.onreadystatechange = function {
// If the request completed and status is OK
if (req.readyState == 4 && req.status == 200) {
// keep in mind that fileNames here are JSON string
// as you should call json_encode($arrayOfFilenames)
// in your php script (upload.php)
var fileNames = xhr.responseText;
}
}
If you'd like consider using a simple library for AJAX requests, like axios. It's promise based HTTP client for the browser, really simple to use and saves you some time and effort cause you don't have to memorize all this stuff you and I have just written.
This is one approach, but I think you can use $_SESSION as well, and it's perfectly valid. My guess is you don't have logged in user at this point, so my idea is as follows:
put filenames into the $_SESSION
use db transactions - as #Marc B suggested - to connect files with
user
if there were no errors just remove filenames from $_SESSION, if there was some, just redirect the user back to the form (possibly with some info what went wrong), and this way he doesn't have to reupload files, cause you have filenames still in $_SESSION

Successful Ajax request but the responseText received is blank?

I am making an Ajax request to update a Mysql table. When I successfully upload a pdf file, the filename and filepath is updated in the table accordingly. The problem I am getting is this. When I upload a small file (414kb) the upload is successful and I am able to update my record. When the file is large (3.6Mb), the upload appears successful but the responseText I get from the Ajax request is a blank. I handled the php side with an IF/ELSE statement and therefore there should be no 'blank' response.
I really do not understand where the problem is. Please see the code below.
My 'upload_max_filesize' is 32M.
JS:
function completeHandler(event){
document.getElementById('p_status').style.color = '#19A347';
if(xmlhttp_file.readyState == 4 && xmlhttp_file.status == 200){
if(xmlhttp_file.responseText == 'update_success'){
console.log('congratulations. Success');
}else{
console.log('fail!');
console.log('responsText: '+xmlhttp_file.responseText);
console.log('xmlhttp_file.readyState: '+ xmlhttp_file.readyState);
console.log('xmlhttp_file.status: '+ xmlhttp_file.status);
}
}
}
PHP:
$move_success = move_uploaded_file($file_TmpPath, "$pdf_dir/$file");
if($move_success){
// ESCAPE CHARACTERS BEFORE INSERTION INTO _DB
// INSERT 'filename', 'filename_uniq', 'filepath'
$file_name = $mysqli->real_escape_string($file_name);
$file_id = $mysqli->real_escape_string($file_id);
$file = $mysqli->real_escape_string($file);
$filepath = $mysqli->real_escape_string("$pdf_dir/$file");
$sql = "UPDATE pdf_library SET filename='$file_name', filename_uniq='$file_id', filepath='$filepath' WHERE id='$idOfPost'";
$result = $mysqli -> query($sql);
if($result){
echo 'update_success';
}else{
echo 'update_fail';
}
}else{
echo 'move fail';
}
When uploading a large pdf - Console:
fail!
new_home.js:1473 responsText:
new_home.js:1474 xmlhttp_file.readyState: 4
new_home.js:1475 xmlhttp_file.status: 200
PHP limits the file size automatically that only certain sizes will be uploaded. It doesn't look like you have a check for the file size to be equal to or lower than the max file size allowed. The default is 2 MB and you have to change it in order to be able to upload more.
PHP change the maximum upload file size
You should do an error debug on $_FILES or move_uploaded_file to get exactly what's occurring (although it likely seems you're running into your MAX_FILE_SIZE configuration as that'd be the first intuition if you are getting differing results on larger file sizes)
You can debug the $_FILES global variable by checking in $_FILES['filename']['error']
http://php.net/manual/en/features.file-upload.errors.php

making a loop with jquery, Ajax and PHP

i want to make a loop in jquery, Ajax and PHP.
my pages are:
shop.php
do_ajax.php
in the shop.php are variable $p_productid is 1 and $j_productid is $p_productid
var j_productid = <?= $p_productid ?>;
now i do j_productid++ so the output from $j_productid is 2
now i'm posting this with ajax to do_ajax.php
in the do_ajax.php are variable $pa_productid is $_POST['$j_productid'];
now i can place this on html, but i want to set this value in too the variable on $p_productid on shop.php
how i need to do this?
there is working a swipe system in this case so only with php it isnt working i need to work with jquery that's why am i doing this on this way. i got an another solution without AJAX but i want that you cant see on the client side the webpage is refreshing.
JQUERY
wipeLeft: function() {
var j_ProductId = <?= $g_ProductId ?>;
var j_Swiped = 1;
if (j_ProductId < <?= $l_LastProduct ?>){
j_ProductId++
//document.swiping.productid.value = j_ProductId;
//document.swiping.submit();
$.ajax({
url: 'do_ajax.php',
type: 'POST',
data: { swipe : j_Swiped,
productid : j_ProductId},
success: function (data) {
$('.product').html(data);
}
});
}
}
do_ajax.php
if(!empty($_POST['swipe'])){
$l_ProductId = $_POST['productid'];
echo $l_ProductId;
}
You need to understand that the JavaScript (even if generated dynamically by PHP) is not running the same time that PHP is running. Your workflow will be something like this:
PHP script (shop.php) is invoked
PHP script generates output, HTML and JS mixed.
These are all in server side until the web server sends the output to client (browser)
In browser HTML displays and JS runs with starting values that you generated previously by PHP. But in this time, PHP has been finished, not running anymore. PHP variables are not alive anymore.
JS interacts with the user in browser, we can say it's running continuously.
Triggered by an action (swipe) JS sends an (ajax) request from client side to server side. This request transfers the new value to server side, and invokes another PHP script (do_ajax.php). You do whatever you want with the new value (process it and or store it) in server side. You need to understand that you are in a completely disjunct scope in PHP than in your first PHP script. (distinct in time too)
If you want to be sure that, in case of a page reload, the (product ID) value will be the updated value, you need to store it somewhere (user session, key-value store, database, or any persistent) when you get it in server side (so in do_ajax.php) and later load this value in the beginning of your shop.php script ...which will pass it to the JS, and so on. The workflow starts again.

check script status in PHP using ajax

I have a file upload page in my application. I need to show "Uploading" while file is uploading then show "Processing" while file is processing. Then after completion of script my page got redirected to some url.
I have tried to use PHP SESSIONS in the script. As in code below:
$_SESSION['uploaded']=0;
if (!empty($_FILES)) {
$tempFile = $_FILES['file']['tmp_name'];
$targetPath = dirname( __FILE__ ) . $ds. $storeFolder . $ds;
$_FILES['file']['name']=date('Ymdhis').$_FILES['file']['name'];
$targetFile = $targetPath. $_FILES['file']['name'];
if(move_uploaded_file($tempFile,$targetFile)){
$_SESSION['uploaded']=1;
//some processing here which takes some 4-5second to complete
}
}
After file upload complete I update session. I am checking session every second by calling following function in javascript:
function countdown(seconds){
console.log(<?php echo $_SESSION['uploaded']; ?>);
if(<?php echo $_SESSION['uploaded']; ?>==0){
setTimeout(function() {
//uploading
seconds--;
countdown(seconds);
}, 1000);
}
else{
//processing
}
}
After searching from google for long time I came to know that in a single script SESSION is locked till script execution completed. Then I used session_write_close(); But it also not works. I am always getting 0 value of SESSION.
Please help me figuring out solution in simplest way. Thanks.
UPDATE
Unable to make it work with Ajax request also. So further tried using the MySQL table.
What I do is create table when upload script is called. Then insert value of status=0 in it using following code:
$session=session_id();
$stmt=$conn->prepare("DROP TABLE IF EXISTS $session");
$stmt->execute();
$stmt=$conn->prepare("CREATE TABLE $session (id INT(11), status INT(11))");
$stmt->execute();
$stmt=$conn->prepare("INSERT INTO $session VALUES(1,0)");
$stmt->execute();
Then after upload completion I update the status to 1 and do the processing on file.
Then after successful completion of script I redirect to result page and drop table using session_id().
But My Ajax script which is checking status every second doesn't respond till the upload.php script ends. I have tried closing connection after every query but in vain. Code on getstatus.php
<?php
session_start();
$session=session_id();
require_once('connect.php');
$stmt=$conn->prepare("SELECT * FROM $session WHERE id=1");
$stmt->execute();
$res=$stmt->fetch(PDO::FETCH_ASSOC);
echo $res['status'];
?>
Unable to find solution for it till now. Help is greatly appreciated. Thanks.
Instead of invoking a PHP process on the server side every second, you could use a static file to check the upload state.
When generating the upload form for the client:
Create a tempnam for a directory that is accessible for the
client.
Write 'uploading' to the temporary file
Store the filename in the session. (Be aware: The user might open multiple upload forms. Store the filenames in an array)
Send the filename to the client as a hidden field.
On the server side after user submitted the form:
Check if filename sent from the client matches a filename stored in the session.
Write 'processing' to the state file
At the end of your upload script write 'finished' to the state file
On the client side after user submits the form, check the upload state by doing ajax requests on the state file.
Remarks
Disable caching for the state file with .htaccess. If this is no option you can achieve the same behavior with a php state script and the upload state saved to a session variable instead of a state file.
To make sure all generated files are deleted register a destroy handler that deletes files generated in the session: http://php.net/manual/en/function.session-set-save-handler.php
<?php echo $_SESSION['uploaded']; ?> is preprocessed by PHP only once, just before this javascript is sent to client. That said, the javascript on client looks like:
function countdown(seconds){
console.log(0);
if(0==0){
setTimeout(function() {
//uploading
seconds--;
countdown(seconds);
}, 1000);
}
else{
//processing
}
}
You should find other way (ajax?) to update information on the client side.
This became too long for a comment.
I'm unsure how you'd respond with progress information with PHP. I tried once and failed.
Socket.io is awesome in Node.js and there is a PHP server emitter. I would potentially give that a go. It should offer near instantaneous communication without waiting for scripts to complete.
Alternatively I would check out Jquery upload, it has a PHP server script. Supports progress bars Jquery Upload. Either implement it directly or check out the source code for how display progress info. I tried having a quick look but couldn't identify how they do it easily.
Why use DATABASE if you can do it on server ?
To save your bandwidth and database traffic you can seperate your process into 2 file
Create upload.php to serve uploading process
$_SESSION['uploaded']=0;
if (!empty($_FILES)) {
$tempFile = $_FILES['file']['tmp_name'];
$targetPath = dirname( __FILE__ ) . $ds. $storeFolder . $ds;
$_FILES['file']['name']=date('Ymdhis').$_FILES['file']['name'];
$targetFile = $targetPath. $_FILES['file']['name'];
if(move_uploaded_file($tempFile,$targetFile)){
// Save path to session var
$_SESSION['uploaded']=$targetFile;
//You can tell client if the uploading process were done and show 'Processing ...'
// Place some code
exit;
}
}
Next, create a file called progress.php
// check
if(!empty($_SESSION['uploaded'])){
// Do your processing code here
// Remove session
unset($_SESSION['uploaded']);
// Then send response to client after your processing were done
echo 'Done';
exit;
}
You can redirect client using jquery as you tagged it. Good luck

Categories

Resources