3

I am using codeigniter 3.1 . I want to post upload data using ajax.

Ajax upload file not working. But when i post the simple form without ajax, it working fine.

I don't know why but no error in console.

HTML

  <?php echo form_open_multipart(site_url("upload/post"), ['id' => 'uploader']) ?>
    <input type="file" name="userfile" value="">
    <input type="submit" value="Submit" />
  <?php echo form_close() ?>

JAVASCRIPT

   $('#uploader').submit(function (event) {
            event.preventDefault();
            $.ajax({
                url: window.location.href + '/post',
                type: "POST",
                dataType: 'json',
                data: new FormData(this)
               });
      });

CONTROLLERS

 public function post() 
    {
        $this->load->helper('url');
        $this->load->helper('form');
        $this->load->library("upload");
        $file = $this->common->nohtml($this->input->post("userfile"));

        $this->upload->initialize(array( 
               "upload_path" => 'upload',
               "overwrite" => FALSE,
               "max_filename" => 300,
               "encrypt_name" => TRUE
            ));

        $this->upload->do_upload('userfile');

        $data = $this->upload->data();

        $image_file = $data['file_name'];

  }
Mehur
  • 131
  • 1
  • 3
  • 11
  • You are not passing file to upload class i.e. `$file`. After initialization you should have something like `if ( ! $this->upload->do_upload('userfile')){/*code*/}`. Check the basic example of upload [here](https://www.codeigniter.com/userguide3/libraries/file_uploading.html#the-controller). – Tpojka Oct 25 '16 at 14:48
  • I already tried but not working. – Mehur Oct 25 '16 at 16:34
  • What is the error? `var_dump('$this->input->post('userfile');exit;` to check if PHP is getting those data. – Tpojka Oct 25 '16 at 16:43
  • No error found. I have more inputs and all are working fine but the file upload not working. – Mehur Oct 25 '16 at 17:27
  • You need to choose wether to use AJAX or default form posting. This way PHP is redirecting page before JS finishes it's job. If you want to use AJAX, you would need to combine some JS library for upload. – Tpojka Oct 25 '16 at 17:48

5 Answers5

3

Another approach to this would be passing to PHP the file encoded in base64:

  • get the selected file from #userfile field using $('#userfile').prop('files')[0];
  • transform the contents of that file into a base64 encoded string using FileReader.readAsDataURL(). We're going to call this content; Here's a similar question showing how to do and expanding the answer & possibilities;
  • send the AJAX passing both the filename and content strings;
  • now on CI, fetch the POST data;
  • base64_decode() the content;
  • fwrite() the result into a file using the filename.

That way also you could avoid POSTing all form fields.

Community
  • 1
  • 1
2

try this.. Post data using FormData() formdata post file also. To get all your form inputs, including the type="file" you need to use FormData object.

$('#post').on('click', function (e) {
    var file_data = $("#userfile").prop("files")[0];      
    var form_data = new FormData();                  
    form_data.append("userfile", file_data)
    $.ajax({
            url: window.location.href+'/post',
            type: 'POST',
            data: form_data,
            async: false,
            success: function (data) {
                alert(data)
            },
            cache: false,
            contentType: false,
            processData: false
        });
   return false;
});

For more...https://abandon.ie/notebook/simple-file-uploads-using-jquery-ajax

Nikhil Vaghela
  • 2,088
  • 2
  • 15
  • 30
  • Ok but i have more inputs in that form which i don't want to send through ajax. Any way to send only file data? – Mehur Oct 25 '16 at 11:33
  • Not working . Getting `Uncaught ReferenceError: formData is not defined(…)` – Mehur Oct 25 '16 at 12:31
1

One of the issues is that file uploading uses a different mechanism than the other form <input> types. That is why $this->input->post("userfile") isn't getting the job done for you. Other answers have suggested using javascript's FormData and this one does too.

HTML

A very simple form for picking a file and submitting it. Note the change from a simple button to <input type="submit".... Doing so makes it a lot easier for the javascript to use the FormData object.

FormData documentation

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <script src="https://code.jquery.com/jquery-2.2.2.js"></script>
        <title>Upload Test</title>
    </head>
    <body>

        <?= form_open_multipart("upload/post", ['id' => 'uploader']); ?>
        <input type="file" name="userfile">
        <p>
            <input type="submit" value="Upload">
        </p>
        <?php echo form_close() ?>

        <div id="message"></div>

        <script>
            $('#uploader').submit(function (event) {
                event.preventDefault();
                $.ajax({
                    url: window.location.href + '/post',
                    type: "POST",
                    dataType: 'json',
                    data: new FormData(this),
                    processData: false,
                    contentType: false,
                    success: function (data) {
                        console.log(data);
                        if (data.result === true) {
                            $("#message").html("<p>File Upload Succeeded</p>");
                        } else {
                            $("#message").html("<p>File Upload Failed!</p>");
                        }
                        $("#message").append(data.message);
                    }
                });
            });
        </script>
    </body>
</html>

JAVASCRIPT

Use FormData to capture the fields. Note that instead of handling the button click we handle the submit event.

$('#uploader').submit(function (event) {
    event.preventDefault();
    $.ajax({
        url: window.location.href + '/post',
        type: "POST",
        dataType: 'json',
        data: new FormData(this),
        processData: false,
        contentType: false,
        success: function (data) {
            //uncomment the next line to log the returned data in the javascript console
            // console.log(data);
            if (data.result === true) {
                $("#message").html("<p>File Upload Succeeded</p>");
            } else {
                $("#message").html("<p>File Upload Failed!</p>");
            }
            $("#message").append(data.message);
        }
    });
});

CONTROLLER

I've added some code that "reports" results to ajax and will display it on the upload page.

class Upload extends CI_Controller
{
    public function __construct()
    {
        parent::__construct();
        $this->load->helper(['form', 'url']);
    }

    public function index()
    {
        $this->load->view('upload_v');
    }

    public function post()
    {
        $this->load->library("upload");
        $this->upload->initialize(array(
                "upload_path" => './uploads/',
                'allowed_types' => 'gif|jpg|png|doc|txt',
                "overwrite" => FALSE,
                "max_filename" => 300,
                "encrypt_name" => TRUE,
        ));

        $successful = $this->upload->do_upload('userfile');

        if($successful)
        {
            $data = $this->upload->data();
            $image_file = $data['file_name'];
            $msg = "<p>File: {$image_file}</p>";
            $this->data_models->update($this->data->INFO, array("image" => $image_file));
        } else {
            $msg = $this->upload->display_errors();
        }

        echo json_encode(['result' => $successful, 'message' => $msg]);
    }

}

This will upload your file. Your work probably isn't done because I suspect that your are not saving all the file info you need to the db. That, and I suspect you are going to be surprised by the name of the uploaded file.

I suggest you study up on how PHP handles file uploads and examine some of the similar codeigniter related questions on file uploads here on SO.

DFriend
  • 8,869
  • 1
  • 13
  • 26
  • Forgot to mention this in the answer but I had to change the upload directory name from `upload` to `uploads`. Maybe you missed that? Other than `data_models->update()` which is a model I don't have the answer code worked for me. When you say, "not working." what exactly do you mean? – DFriend Oct 25 '16 at 21:37
  • Thanks now working. The problem is in my php but i fixed it :) – Mehur Oct 27 '16 at 20:36
  • All working fine but success function not working. `success: function (data) { console.log(data); }` not showing. – Mehur Oct 31 '16 at 21:37
  • But the file uploads OK? – DFriend Oct 31 '16 at 21:44
  • Yes all working fine but success function not working. – Mehur Oct 31 '16 at 21:45
  • Please forgive if is insulting. You know how to view the java console - right. – DFriend Oct 31 '16 at 21:45
  • Do you see the any network traffic coming back from the ajax request? You can examine the response and see what, if anything, the server sends back. – DFriend Oct 31 '16 at 22:11
  • I am using AJAX Debugger Preferences chrome extension and i get this error from console `VM5547:3 XHR Loaded (post - 200 OK - 260.44399999955203ms - 601B) VM5549:3 http://localhost/post VM5550:3 XHR Data Object {startedDateTime: "2016-11-01T20:30:47.384Z", time: 260.44399999955203, request: Object, response: Object, cache: Object…}` – Mehur Nov 01 '16 at 20:34
  • `VM5547:3` sources = `(function (json_args) { var args = JSON.parse(unescape(json_args)); console[args[0]].apply(console, Array.prototype.slice.call(args, 1)); })('%5B%22group%22%2C%22XHR%20Loaded%20%28updatepropic%20-%20200%20OK%20-%20260.44399999955203ms%20-%20601B%29%22%5D');` – Mehur Nov 01 '16 at 20:36
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/127134/discussion-between-dfriend-and-mehur). – DFriend Nov 01 '16 at 21:31
  • Finally i fixed it by removing `dataType: 'json',` , and now working fine. Please update answer. Thank you for all help :) – Mehur Nov 02 '16 at 09:45
1

Controller

public function upload()
{
$this->load->library('upload');

if (isset($_FILES['myfile']) && !empty($_FILES['myfile']))
{
    if ($_FILES['myfile']['error'] != 4)
    {
         // Image file configurations
        $config['upload_path'] = './upload/';
        $config['allowed_types'] = 'jpg|jpeg|png';
        $this->upload->initialize($config);
        $this->upload->do_upload('myfile');
    }
  }
 }

View

<form id="myform" action="<?php base_url('controller/method'); ?>" method="post">
<input type="file" name="myfile">

("#myform").submit(function(evt){
evt.preventDefault();

var url = $(this).attr('action');
var formData = new FormData($(this)[0]);
$.ajax({
    url: url,
    type: 'POST',
    data: formData,
    processData: false,
    contentType: false,
    success: function (res) {
        console.log(res);
    },
    error: function (error) {
        console.log(error);
    }
}); // End: $.ajax()           

}); // End: submit()

Let me know if any query

Muhammad Usman
  • 1,403
  • 13
  • 24
0

you need to submit the form not on click but on submit ... give the form an id and then on submit put ajax

HTML

<?php $attributes = array('id' => 'post'); ?>

<?php echo form_open_multipart(site_url("upload/post",$attributes), ?>
    <input type="file" id="userfile" name="userfile" value="">
    <button id="post">Submit</button>
  <?php echo form_close() ?>

JAVASCRIPT

$('#post').on('submit', function () {

    var formData = new FormData();
    formData.append("userfile",$("#userfile")[0].files[0]);

    $.ajax({
            url: window.location.href+'/post',
            type: "POST",
            data: formData
        });

CONTROLLERS

public function post() 
    {
        $this->load->library("upload");
        $file = $this->common->nohtml($this->input->post("userfile"));
    $this->upload->initialize(array( 
           "upload_path" => 'upload',
           "overwrite" => FALSE,
           "max_filename" => 300,
           "encrypt_name" => TRUE,
        ));

    $data = $this->upload->data();

    $image_file = $data['file_name'];

    $this->data_models->update($this->data->INFO, array(
      "image" => $image_file
        )
      );

}

  • Not working. Getting `upload:24 Uncaught TypeError: Cannot read property '0' of undefined(…)1 – Mehur Oct 25 '16 at 12:30