0

First of all this might be a silly question as there are many topics available on this but seriously I am not being able to get it straight and understand how to make it work.

WHAT I AM TRYING TO DO

I am trying to upload multiple files using AJAX and PHP.

PROBLEM

  • I cant figure out how to pass the data to the PHP script using AJAX. I don't want to use a form and a submit button for uploading.
  • Tried using a form and submitting it using jQuery still couldn't make it.

HTML

<div id="content">
    <div id="heading">Upload your files seamlessly</div>
    <a href="#"><div id="upload" class="button" title="Upload your files"><i class="fa fa-cloud-upload fa-align-center" aria-hidden="true"></i>
</div></a>
    <a href="view.php"><div id="view" class="button" title="View all files on my cloud"><i class="fa fa-eye fa-align-center" aria-hidden="true"></i>
</div></a>
</div>

<form id="fileupload" method="POST" enctype="multipart/form-data">
<input type="file" multiple name="uploadfile[]" id="uploadfile" />
</form>

JS

<script type="text/javascript">
$(document).ready(function(){
    $('#upload').click(function(){
        $('input[type=file]').click();
        return false;
    });

    $("#uploadfile").change(function(){
         //submit the form here  
         $('#fileupload').submit();
    });
});
</script>

PHP

<?php
if(isset($_FILES['uploadfile'])){

    $errors= array();

    foreach($_FILES['uploadfile']['tmp_name'] as $key => $tmp_name ){
        $file_name = $key.$_FILES['uploadfile']['name'][$key];
        $file_size =$_FILES['uploadfile']['size'][$key];
        $file_tmp =$_FILES['uploadfile']['tmp_name'][$key];
        $file_type=$_FILES['uploadfile']['type'][$key]; 
        if($file_size > 2097152){
            $errors[]='File size must be less than 2 MB';
        }       

        //$query="INSERT into upload_data (`USER_ID`,`FILE_NAME`,`FILE_SIZE`,`FILE_TYPE`) VALUES('$user_id','$file_name','$file_size','$file_type'); ";

        $desired_dir="storage";

        if(empty($errors)==true){
            if(is_dir($desired_dir)==false){
                mkdir("$desired_dir", 0700);        // Create directory if it does not exist
            }

            if(is_dir("$desired_dir/".$file_name)==false){
                move_uploaded_file($file_tmp,"$desired_dir/".$file_name);
            }
            else{                                   // rename the file if another one exist
                $new_dir="$desired_dir/".$file_name.time();
                 rename($file_tmp,$new_dir) ;               
            }
         //mysql_query($query);         
        }
        else{
                print_r($errors);
        }
    }
    if(empty($error)){
        echo "Success";
    }
}
?>

Any help would be appreciated.

Ayan
  • 1,952
  • 2
  • 21
  • 58
  • As far as I know: Using a form input, and post it, is the only way to upload local files from a browser. – KIKO Software Jun 18 '16 at 15:17
  • You mean using a form? – Ayan Jun 18 '16 at 15:20
  • The user of the browser has to give your html/javascript code access to local files. This is done with an ``. That's probably part of a form. But the user has to initiate the upload. Once that is done your javascript can take over. Submit button is not needed. In JQuery you can use `$(
    ).submit();`.
    – KIKO Software Jun 18 '16 at 15:22
  • Is there no way without a form? – Ayan Jun 18 '16 at 15:33
  • Can you be more specific? What's wrong with using a form? You want to download files from an user's computer without their consent? The only files you can get at, without a form, are cookies. – KIKO Software Jun 18 '16 at 15:34
  • I am not downloading files but allowing users to upload files without the need to press submit button. Actually I had seen something like this on script in github – Ayan Jun 18 '16 at 15:37
  • You do not need a submit button. Even if you use a form. – KIKO Software Jun 18 '16 at 15:38
  • Can you show me an example? – Ayan Jun 18 '16 at 15:39
  • It's in the documentation: https://api.jquery.com/submit – KIKO Software Jun 18 '16 at 15:55
  • This [answer](http://stackoverflow.com/a/21045034/1022914) should help you with the JS part. You'll probably need to iterate over the files and append them to the FormData. – Mikey Jun 18 '16 at 16:18
  • @KIKOSoftware I updated my code but still no uploads take place. Check my updated code. – Ayan Jun 18 '16 at 17:13
  • Your `
    ` tag is incomplete, you need an `action` attribute that refers to the php script that accepts the file upload. See: http://www.w3schools.com/tags/tag_form.asp
    – KIKO Software Jun 18 '16 at 20:38
  • Even with an action attribute it doesn't work . – Ayan Jun 19 '16 at 02:42
  • http://stackoverflow.com/questions/24168040/upload-multiple-files-with-php-and-jquery/24168617#24168617 – Alexander Ceballos Jun 19 '16 at 21:46

1 Answers1

0

This is a very simple example of what you want to do.

HTML

Wrap your inputs within a form. Why? Because it is the easiest way to do it.

<form action="process.php" method="post">
    <input type="file" multiple name="uploadfile[]">
    <input type="submit" value="Upload"> 
</form>

JavaScript

Attach an onsubmit event handler to your form. Use $.ajax() to send a POST request.

Pass your form element i.e. this into the constructor of a FormData object and use it as your data when you send the request as shown below. You need to make sure that you set processData and contentType as false also for this to work.

$(function () {
    $('form').on('submit', function (e) {
        e.preventDefault();
        // send request
        $.ajax({
            url: this.action, 
            type: this.method, 
            data: new FormData(this), // important
            processData: false, // important 
            contentType: false, // important
            success: function (res) {
                alert(res);
            }
        });
    });
});

PHP (process.php)

Let's clean up your PHP.

<?php
// always a good idea to turn on errors during development
error_reporting(E_ALL);
ini_set('display_errors', 1);

$dir = './storage';
$errors = [];

if (isset($_FILES['uploadfile'])) {
    $files = $_FILES['uploadfile'];
    // create directory if it does not exist
    !is_dir($dir) && mkdir($dir, 0700);
    // validate & upload files
    foreach (array_keys($files['tmp_name']) as $key) {
        $file = [
            'name' => $files['name'][$key],
            'size' => $files['size'][$key],
            'tmp_name' => $files['tmp_name'][$key],
            'type' => $files['type'][$key],
            'error' => $files['error'][$key]
        ];
        // skip if no file was given
        if ($file['error'] === UPLOAD_ERR_NO_FILE) {
            continue;
        }
        // get file extension
        $file['ext'] = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
        // generate a unique name (!)
        $file['name'] = uniqid() . '.' . $file['ext'];
        // validate
        if (!file_exists($file['tmp_name']) || 
            !is_uploaded_file($file['tmp_name']) ||
            $file['error'] !== UPLOAD_ERR_OK) {
            $errors[$key] = 'An unexpected error has occurred.';
        } elseif ($file['size'] > 2097152) {
            $errors[$key] = 'File size must be less than 2 MB';
        // upload file
        } elseif (!move_uploaded_file($file['tmp_name'], $dir . '/' . $file['name'])) {
            $errors[$key] = 'File could not be uploaded.';
        }
    }
}

if ($errors) {
    print_r($errors);
} else {
    echo 'no errors';
}
?>

(!) Do keep in mind that uniqid() is actually not unique.

Mikey
  • 6,432
  • 4
  • 20
  • 36
  • I tried this but in any case it keeps alerting me with "No errors" – Ayan Jun 20 '16 at 05:24
  • Debug the code by putting `echo`s at different points in the code and see where it fails from that. I ran this code on my local server and it worked fine. – Mikey Jun 20 '16 at 22:12