Ajax not moving my Uploaded File to where it needs to be - php

The concept is pretty simple, I need to upload a file without refreshing the page, so I'm using an ajax. I've never done an upload ajax before, so I'm not sure what I'm missing here.
function uploadAttachment(){
var name = document.getElementById("file").files[0].name;
var did = <? echo $did ?>;
var form_data = new FormData();
var oFReader = new FileReader();
oFReader.readAsDataURL(document.getElementById("file").files[0]);
var f = document.getElementById("file").files[0];
var fsize = f.size||f.fileSize;
if(fsize > 2000000)
{
alert("File Size is too large. Please make sure your file's size is less than 2MB.");
}
else
{
form_data.append("file", document.getElementById('file').files[0]);
$.ajax
({
url:"/assets/ajax/disciplinaries_upload.php?did="+did,
method:"POST",
data: form_data,
contentType: false,
cache: false,
processData: false,
beforeSend:function()
{
$('#uploaded_file').html("<label class='text-success'>File Uploading...</label>");
},
success:function(data)
{
$('#uploaded_file').html(data);
}
});
}
};
And my disciplinaries_upload.php ajax as follows;
<?php
$did = $_GET['did'];
if($_FILES["file"]["name"] != '')
{
$test = explode('.', $_FILES["file"]["name"]);
$fname = reset($test);;
$ext = end($test);
$name = $fname . '_' .$did. '.' . $ext;
$location = '/assets/uploads/files/disciplinary_attachments/' . $name;
move_uploaded_file($_FILES["file"]["tmp_name"], $location);
if (file_exists($location)) {
echo '<label class="text-success">File Uploaded Successfully</label>';
} else {
echo '<label style="color: red">File Upload Failed</label><br> Original File Name: '.$_FILES["file"]["name"].'<br> Extension: '.$ext.'<br> Newly Generated Name: '.$name.'<br>File Location: '.$location;
}
}
?>
The problem seems to be that it's not actually uploading the file. I'm receiving the upload failed error that I've created which looks as follows;
File Upload Failed
Original File Name: test.txt
Extension: txt
Newly Generated Name: test_25.txt
File Location: /assets/uploads/files/disciplinary_attachments/test_25.txt
So by the looks of it, it does actually receive the file and knows where it needs to go... it just doesn't actually upload it there.

Thanks to both #Jay Blanchard and #kerbholz the code now works. All I had to do was change
$location = '/assets/uploads/files/disciplinary_attachments/' . $name;
to
$location = '/usr/www/users/keepnxcanc/assets/uploads/files/disciplinary_attachments/' . $name;

Looks like this issue might happen because of Upload file size limitation and type or Destination write permeation or Destination path is not satisfying or file upload over http/https is blocked by security team.
Solution:
Upload file size limitation: By default web servers might allow to upload up to 1MB. you need to change the property called Max_upload_size to you requirement.
Destination write permeation: Some times we might forgot to remove wright protection to upload destination folder. So, Change the permissions to disable wright protection of the destination folder.
Destination path is not satisfying: Some times the destination path might not clear to make changes in. So, better to provide complete path.
code snip1: place at the top of you logic in index.php
define("BASE_PATH", __DIR__);
code snip2: change this $location in disciplinaries_upload.php
$location = BASE_PATH . '/assets/uploads/files/disciplinary_attachments/' . $name;
File upload over http/https: if your security team is enabling any restrictions, as them to enable. or make your self whitelist.
finally: a slight change in your code.
Code snip:
<?php
//comment this two lines in production
error_reporting(E_ALL);
ini_set('display_errors', 1);
//define("BASE_PATH", __DIR__); //if both index.php and disciplinaries_upload.php in same location, comment this else keep it in index.php
$did = $_GET['did'];
if(count($_FILES) > 0)
{
$test = explode('.', $_FILES["file"]["name"]);
$fname = reset($test);;
$ext = end($test);
$name = $fname . '_' .$did. '.' . $ext;
$location = BASE_PATH . '/assets/uploads/files/disciplinary_attachments';
$permition_cod = substr(sprintf('%o', fileperms($location)), -4);
#chmod($location, "0777");
if (move_uploaded_file($_FILES["file"]["tmp_name"], $location.'/'.$name)) {
echo '<label class="text-success">File Uploaded Successfully</label>';
} else {
echo '<label style="color: red">File Upload Failed</label><br> Original File Name: '.$_FILES["file"]["name"].'<br> Extension: '.$ext.'<br> Newly Generated Name: '.$name.'<br>File Location: '.$location;
}
#chmod($location, $permition_cod);
}
?>
Good luck...

Related

bootstrap fileinput, show uploaded files and delete them

how can i show and delete previously uploaded files with the great bootstrap-fileinput plugin from krajee, my code is:
html:
<script>
$("#images").fileinput({
uploadAsync: true,
uploadUrl: "upload.php"
}).on("filebatchselected", function(event, files) {
$("#images").fileinput("upload");
});
</script>
upload.php:
<?php
if (empty($_FILES['images'])) {
echo json_encode(['error'=>'No files found for upload.']);
return;
}
$images = $_FILES['images'];
$success = null;
$paths= [];
$filenames = $images['name'];
for($i=0; $i < count($filenames); $i++){
$ext = explode('.', basename($filenames[$i]));
$target = "uploads" . DIRECTORY_SEPARATOR . basename($filenames[$i]);
if(move_uploaded_file($images['tmp_name'][$i], $target)) {
$success = true;
$paths[] = $target;
} else {
$success = false;
break;
}
}
if ($success === true) {
$output = ['uploaded' => $paths];
} elseif ($success === false) {
$output = ['error'=>'Error while uploading images. Contact the system administrator'];
foreach ($paths as $file) {
unlink($file);
}
} else {
$output = ['error'=>'No files were processed.'];
}
echo json_encode($output);
?>
Has anyone an idea ? i think i have to scan the uploads dir and send it back with json or use $output, but i dont know how to this ?
Since you are using json to upload files, you can use it to delete them too. Make another ajax call to the server by sending an array of the image URLs that you want to remove. Then with PHP you can simply unlink them.
So for example: http://jsfiddle.net/fdzsLa0k/1/
var paths = []; // A place to store all the URLs
// Loop through all images
// You can do it for a single image by using an id selector and skipping the looping part
$('.uploaded-img').each(function(i, v) {
paths.push(this.src); // Save found image paths
})
console.log(paths); // Preview the selection in console
// Send the URLs to the server for deletion
$.ajax({
method: 'post',
data: { images: paths },
url: 'ajax.php' // Replace with your ajax-processing file
}).success(function(response) {
console.log(response); // Do fun stuff: notify user, remove images from the loaded HTML
});
uuuhh, the fileinput script need php version higher than 5.3.3, because the plesk panel of my hosting provider supports only 5.3.3 i have the problems, since 11.5 plesk supports multiple php version for each domain on the server, now with php 5.6 everything works great !

PHP - Renaming a file to disallow duplicates

So I am using this script to upload a file to a directory and show it live.
<?php
function UploadImage($settings = false)
{
// Input allows you to change where your file is coming from so you can port this code easily
$inputname = (isset($settings['input']) && !empty($settings['input']))? $settings['input'] : "fileToUpload";
// Sets your document root for easy uploading reference
$root_dir = (isset($settings['root']) && !empty($settings['root']))? $settings['root'] : $_SERVER['DOCUMENT_ROOT'];
// Allows you to set a folder where your file will be dropped, good for porting elsewhere
$target_dir = (isset($settings['dir']) && !empty($settings['dir']))? $settings['dir'] : "/uploads/";
// Check the file is not empty (if you want to change the name of the file are uploading)
if(isset($settings['filename']) && !empty($settings['filename']))
$filename = $settings['filename'] . "sss";
// Use the default upload name
else
$filename = preg_replace('/[^a-zA-Z0-9\.\_\-]/',"",$_FILES[$inputname]["name"]);
// If empty name, just return false and end the process
if(empty($filename))
return false;
// Check if the upload spot is a real folder
if(!is_dir($root_dir.$target_dir))
// If not, create the folder recursively
mkdir($root_dir.$target_dir,0755,true);
// Create a root-based upload path
$target_file = $root_dir.$target_dir.$filename;
// If the file is uploaded successfully...
if(move_uploaded_file($_FILES[$inputname]["tmp_name"],$target_file)) {
// Save out all the stats of the upload
$stats['filename'] = $filename;
$stats['fullpath'] = $target_file;
$stats['localpath'] = $target_dir.$filename;
$stats['filesize'] = filesize($target_file);
// Return the stats
return $stats;
}
// Return false
return false;
}
?>
<?php
// Make sure the above function is included...
// Check file is uploaded
if(isset($_FILES["fileToUpload"]["name"]) && !empty($_FILES["fileToUpload"]["name"])) {
// Process and return results
$file = UploadImage();
// If success, show image
if($file != false) { ?>
<img src="<?php echo $file['localpath']; ?>" />
<?php
}
}
?>
The thing I am worried about is that if a person uploads a file with the same name as another person, it will overwrite it. How would I go along scraping the filename from the url and just adding a random string in place of the file name.
Explanation: When someone uploads a picture, it currently shows up as
www.example.com/%filename%.png.
I would like it to show up as
www.example.com/randomstring.png
to make it almost impossible for images to overwrite each other.
Thank you for the help,
A php noob
As contributed in the comments, I added a timestamp to the end of the filename like so:
if(isset($settings['filename']) && !empty($settings['filename']))
$filename = $settings['filename'] . "sss";
// Use the default upload name
else
$filename = preg_replace('/[^a-zA-Z0-9\.\_\-]/',"",$_FILES[$inputname]["name"]) . date('YmdHis');
Thank you for the help

Make PHP return with URL after jQuery upload?

I am using Hayageek's jQuery upload from: http://hayageek.com/docs/jquery-upload-file.php - After the file is done uploading, how can I make it return the URL to the file, but with staying on the same page? Here is my example code:
jQuery upload:
$(document).ready(function() {
$("#fileuploader").uploadFile({
url: "upload.php",
allowedTypes: "jar",
fileName: "myfile"
});
});
upload.php:
<?php
$output_dir = "uploads/";
if (isset($_FILES["myfile"])) {
$ret = array();
$error = $_FILES["myfile"]["error"];
if (!is_array($_FILES["myfile"]["name"])) {
$fileName = $_FILES["myfile"]["name"];
move_uploaded_file($_FILES["myfile"]["tmp_name"], $output_dir . $fileName);
$ret[] = $fileName;
}
echo json_encode($ret);
}
?>
I grabbed all the code from his website. Basically it grabs a file with uploadFile(), then the PHP grabs the file and puts it in the /uploads/ folder. But while I am on the page, how can I make it return back with the URL it uploads to?
I know you can estimate the URL (as the file name won't change, so it will always be http://website.com/uploads/file_name.jar), but I need the server to reply back with the URL once it's done. Thanks in advance!

PHP can't pick up file

I've been trying to create a registration form that requires students to upload documents at the very end. However, after picking up the form values via jQuery, the PHP document can't seem to pick up my uploaded form. Any ideas?
Form:
<form id="joinUs" enctype="multipart/form-data" method="post">
<!--various form fields-->
<input type="file" name="transcript" id="transcript">
<div class="button" id="submit">Submit!</div>
</form>
jQuery:
$("#submit").click(function(){
//firstName, lastName, grade, studentID, email, phone are all form values
var data = "firstName="+firstName+"&lastName="+lastName+"&grade="+grade+"&studentID="+studentID+"&email="+email+"&phone="+phone;
$.ajax({
type: "POST",
url: "join_submit.php",
data: data,
success: function() {
location.href="http://mvcsf.com/new/success.php";
}
});
join_submit.php
$allowedExtensions = array("pdf");
$max_filesize = 20000;
$upload_path = "docs/transcripts";
$filename = $_FILES["transcript"]["name"];
$filesize = $_FILES["transcript"]["size"];
$extension = $_FILES["transcript"]["type"];
if ($_FILES["transcript"]["error"] > 0) {
echo "Error: " . $_FILES["transcript"]["error"] . "<br />";
}
else if((in_array($extension, $allowedExtensions)) && ($filesize < $max_filesize)) {
move_uploaded_file($_FILES["transcript"]["tmp_name"], $upload_path . $filename);
}
I ran this, and I got no errors. I also tried to print out the file name, except nothing printed out.
This should do it for you :
$("#submit").click(function () {
var transcript = $("#transcript").val();
var data = "firstName=" + firstName + "&lastName=" + lastName + "&grade=" + grade + "&studentID=" + studentID + "&email=" + email + "&phone=" + phone;
var formData = new FormData();
formData.append("file", transcript);
formData.append("data", data);
$.ajax({
type: "POST",
url: "join_submit.php",
enctype: 'multipart/form-data',//optional
cache: false,
contentType: false,
processData: false,
data: {
file: file
data: data
},
success: function () {
location.href = "http://mvcsf.com/new/success.php";
}
});
});
Cheers
First, In your code, you are posting data with $.ajax({...}) and the data sent is
"firstName="+firstName+"&lastName="+lastName+"&grade="+grade+"&studentID="+studentID+"&email="+email+"&phone="+phone;
There is no transcript at all.
Secondly, and most important, you cannot post file with $.ajax({...}) like that, it will not working like that. As #Roy M J says, you should take a look at FormData (for recent browser only), or take a look on the web for an upload jQuery plugin (don't re-invent the whell, some good plugin already exists :))
Take a look here
You cannot send a file like you do the values of HTML elements. There are two methods to file upload, the one I've used successfully is the AJAX method using a third-party feature called 'AjaxUploader'.You can download it here via GitHub. Once you've done it, add the ajaxuploader.js file in your 'js' folder (or wherever you've put all of your script files), include the file in the HTML page where you've to use the uploader. Now, uploading is as simple as follows.
HTML:
<input type="file" name="transcriptUploader" id="transcriptUploader" value="Upload" />
jQuery (you need to have the jQuery file included in your page):
new AjaxUpload('transcriptUploader', {
action: "page_to_handle_upload.php", // You need to have either a separate PHP page to handle upload or a separate function. Link to either one of them here
name: 'file',
onSubmit: function(file, extension) {
// This function will execute once a user has submitted the uploaded file. You can use it to display a loader or a message that the file is being uploaded.
},
onComplete: function(file, response) {
// This function will execute once your file has been uploaded successfully.
var data = $.parseJSON(response); // Parsing the returning response from JSON.
if(data.error == 0)
{
// If the file uploaded successfully.
}
else if(data.error == "size"){
// If the response object sent 'size' as the error. It means the file size exceeds the size specified in the code.
}
else if(data.error == "type"){
// If the response object sent 'type' as the error. It means the file type is not of that specified in the code (in your case, pdf).
}
else{
// In case the file didn't upload successfully or the code didn't return a usual error code. It is still an error so you need to deal with it appropriately.
}
}
});
Your back-end PHP code that will be doing all the heavy lifting (uploading the file, checking extensions, moving it etc):
if(isset($_FILES)) // Checking if a file is posted.
{
if ($_FILES['file']['error'] == 0) //Checking if file array contain 0 as an error. It means AJAX had no error posting the file.
{
$response = array(); // Initializing a new array.
$allowedExts = array("pdf"); // Allowable file format.
$filename = stripslashes($_FILES['file']['name']); // Storing file name.
//$extension = strtolower(self::_getExtension($filename)); // Fetching file extension.
// Code block to extract file extension and storing it in a variable called $extraction.
$i = strrpos($str, ".");
if (!$i)
{
$extension = "";
}
$l = strlen($str) - $i;
$extension = strlower(substr($str, $i + 1, $l));
$size = $_FILES['file']['size']; // Storing file size (in bytes).
$fileNameAfterUpload = md5((time() + microtime())) . '.' . $extension; // Concatinating file name and extension.
$baseSystemPath = "/var/www/<your_folder_name>/uploaded_transcripts/" // Path on which the file will be uploaded. Need to be relative web path.
$maxSize = 10*10*1024; // Storing file size. Be advised the file size is in bytes, so this calculation means max file size will be 10 MB.
$webPath = "uploaded_transcripts/". $filename; // Creating web path by concatinating base web path (the folder in which you'd be uploading the pdf files to) with file name.
if (in_array($extension, $allowedExts)) // Checking if file contains allowabale extensions.
{
if($size <= $maxSize) // Checking if the size of file is less than and equal to the maximum allowable upload size.
{
$moved = move_uploaded_file($_FILES['file']['tmp_name'], $webPath); // Moving the file to the path specified in $webPath variable.
if($moved == true)
{
$response['error'] = 0; // If moved successfully, storing 0 in the response array.
$response['path'] = $webPath; // Storing web path as path in the response array.
$response['filename'] = $filename; // Storing file name in the response array.
}
else
{
$response['error'] = 'internal'; // If move isn't successfull, return 'internal' to AJAX.
}
}
else
{
$response['error'] = 'size'; // If file size is too small or large, return 'size' to AJAX.
}
}
else
{
$response['error'] = 'type'; // If file type is not that of defined, return 'type' to AJAX.
}
echo json_encode($response); // Returning the response in JSON format to AJAX.
}
}
Do let me know if you need further assistance.
P.S: Don't forget to mark it as an answer if it worked.

Adding Random Number to Uploaded File

I'm using Valum's Ajax-Uploader script to upload files to my server. Because there's a good chance of the uploaded files have the same name I add a random number to the filename. The problem is that the ajax uploader is returning the original filename into the input[type=text] instead of the new filename with the random number added. I've tried echo $file; instead of echo "success"; , but all that happens is that the file is uploaded, and the script returns with the pop-up error.
jQuery(function() {
var url = "http://example.com/uploads/samples/";
var button = jQuery('#up');
new AjaxUpload(button, {
action: 'upload.php',
name: 'upload',
autoSubmit: true,
onSubmit: function(file, ext) {
// do stuff while file is uploading
},
onComplete: function(file, response) {
if (response === "success") {
$('input[type=text]').val(url + file);
} else {
jAlert('Something went wrong!', 'Error!');
}
}
});
});
upload.php
<?php
$uploaddir = '/path/to/uploaddir/';
$file = basename($_FILES['file']['name']);
if($_FILES['file']['name']) {
$file = preg_replace('/\s+/', '_', $file);
$rand = rand(0000,9999);
if (move_uploaded_file($_FILES['file']['tmp_name'], $uploaddir . $rand . $file)) {
echo "success";
} else {
echo "error";
}
}
?>
Change
$('input[type=text]').text(url + file);
To
$('input[type=text]').val(url + file);
Client code and server code exist completely independently of each other. Basically, your JavaScript code has no way of knowing what your PHP code just did. url doesn't update automatically when you change it in the PHP file.
An alternate solution would be to have your PHP code echo the new filename, or echo an error message.
For example:
PHP
<?php
if (move_uploaded_file($_FILES['file']['tmp_name'], $uploaddir . $rand . $file)) {
// Everything went well! Echo the dollar sign ($) plus the new file name
echo '$' . $_FILES['file']['tmp_name'], $uploaddir . $rand . $file;
} else {
echo "error";
}
?>
JS
onComplete: function(file, response) {
// If the first character of the response is the "$" sign
if (response.substring(0,1) == "$") {
$('input[type=text]').val(response.substring(1));
} else {
jAlert('Something went wrong!', 'Error!');
}
}
I would like to suggest using date and time to create a unique random number.
You can use following function in your code, I am fully trusted on this function because I already use this in my project.
`
/**
* This function return unique string as a key
*/
public static function getUniqueKey(){
$currentDateTime = date("YmdHisu");
return $currentDateTime . BTITTools::createRandomString(3);
}
`
# My Code Programs

Categories