1

I've created a functionality on my website where user's can change the background image via upload. The procedure is following:

User goes to settings page and selects an image file to be uploaded. After selecting image, the browser will output it so that user can preview it before actually saving it's file to in to the folder and filepath in to the database. After that, if user is happy with the result, he can save it to the folder by pressing "Upload Background Image" button.

All of the above is handled with AJAX.

I am having trouble to just output the image to the browser without actually saving it twice, first into tests folder and after that into backgrounds folder.

I'm using CodeIgniter as my backend framework and jQuery for my AJAX requests.

Here are my methods for outputting (testing) and saving the image:

public function test_image()
{
    if($this->input->is_ajax_request())
    {

        // This part of code needs to be replaced to only just output the image (return it as a JSON), not actually saving it to another a folder
        $ext = pathinfo($_FILES['userfile']['name'], PATHINFO_EXTENSION);
        $new_img_name = random_string('unique'). "." . $ext;

        $config['upload_path'] = './public/images/uploads/tests';
        $config['allowed_types'] = 'gif|jpg|jpeg|png';
        $config['max_size'] = '1000000';
        $config['max_width'] = '2000';
        $config['max_height'] = '1600';
        $config['file_name'] = $new_img_name;

        $this->load->library('upload', $config);

        if (!$this->upload->do_upload()) {

            $this->output->set_content_type('application_json');
            $this->output->set_output(json_encode(array('image_errors' => $this->upload->display_errors('<p class="text-center">','</p>'))));
            return false;

        } else {

            $this->output->set_content_type('application_json');
            $this->output->set_output(json_encode(array('userfile' => $new_img_name)));
        }

    } else {

        echo "Not an ajax request";
    }
}

// This method works properly
public function upload_background_image()
{
    if (isset($_POST))
    {
        $ext = pathinfo($_FILES['userfile']['name'], PATHINFO_EXTENSION);
        $new_img_name = random_string('unique'). "." . $ext;

        $config['upload_path'] = './public/images/uploads/backgrounds';
        $config['allowed_types'] = 'gif|jpg|jpeg|png';
        $config['max_size'] = '1000000';
        $config['max_width'] = '2000';
        $config['max_height'] = '1600';
        $config['file_name'] = $new_img_name;

        $this->load->library('upload', $config);

        if (!$this->upload->do_upload()) {

            $this->output->set_content_type('application_json');
            $this->output->set_output(json_encode(array('image_errors' => $this->upload->display_errors('<p class="text-center">','</p>'))));
            return false;

        } else {

            $this->load->model('user_model');
            $user_id = $this->session->userdata('user_id');

                $upload_photo = $this->user_model->updateUserInfo($user_id, ['body_background_url' => $new_img_name]);

                if ($upload_photo === true) {

                    $this->session->set_userdata(['body_background_url' => $new_img_name]);
                    redirect(base_url());
                }
        }
    }

}

And here's my AJAX:

        $("#bg-cover-file").change(function(e) {
            e.preventDefault();

            var form = $(this).closest('form');

            form.ajaxSubmit({
                dataType: 'json',
                beforeSubmit: function() {
                },
                success: function(response) {
                    if(response.userfile) {

                        // Output the image
                        $('.test-image').attr('src', response.userfile);
                        $('span.file-input').hide();

                        // Change the form action attribute
                        var new_path = 'uploads/upload_background_image';
                        form.attr('action', new_path);

                    } else {
                        $('#error-modal').modal('show');
                        $("#error-body").html(response.image_errors);
                        return false;
                    }
                }
            });
            return false;
        });
Cooper
  • 152
  • 1
  • 10
  • So are you uploading the image to display the preview and then uploading it again if they want to save the image? – NewToJS Mar 10 '15 at 14:00
  • Exactly, you got the point – Cooper Mar 10 '15 at 14:00
  • Why not go ahead and save it to the upload folder and just hold off on associating it in the database until the user presses save? There's not really any reason to have the user upload twice. – acupofjose Mar 10 '15 at 14:02
  • Can preview using script without any upload ... then upload when final selection made – charlietfl Mar 10 '15 at 14:03
  • 2
    There is already an answer here for this , use the FileReader http://stackoverflow.com/questions/14069421/in-html5-how-to-show-preview-of-image-before-upload – Clain Dsilva Mar 10 '15 at 14:07
  • @Cooper Ah, I did create a demo for you but it appears the answer has already been submitted. – NewToJS Mar 10 '15 at 14:14
  • @NewToJS Strange since the aren't any answers – Cooper Mar 10 '15 at 14:24
  • @Cooper the link posted by Clain Dsilva shows you how to use FileReader. Please read the answer on that page, if you don't understand it then let me know and I will submit my demo and put as many comments in to explain each step. – NewToJS Mar 10 '15 at 14:27

3 Answers3

2

--Working Demo--

I have put comments in this demo to explain what the steps are so please read them.

If you don't understand anything in this answer please leave a comment below and i will update the answer until you understand line for line. You don't learn from copy/paste so please be sure to understand the answer.

function MyFunction() {
var img=document.getElementById('BackgroundImage');
var Status=document.getElementById('Status');
var savebtn=document.getElementById('savebtn');
/* SetBG will target the body tag of the web page.
You can change this to any element - 
var SetBG=document.getElementById('YourID').style;
*/
var SetBG=document.body.style;
//Split the image name
var fileExt=img.value.split('.');
//Use the last array from the split and put to lowercase 
var fileformat=fileExt[fileExt.length -1].toLowerCase();
// Check the file extension (Image formats only!)
if((fileformat==='jpg')||(fileformat==='gif')||(fileformat==='png')||(fileformat==='jpeg')) {    
    if (img.files && img.files[0]) {
    var reader = new FileReader();
    reader.onload = function (e) {
    //----Image is ready for preview.
    SetBG.background='url('+e.target.result+') no-repeat center center fixed';
    /*---- Optional, Set background as cover ---*/
    SetBG.backgroundSize="cover";
 SetBG.OBackgroundSize="cover";
 SetBG.webkitBackgroundSize="cover";
    //--Hide Loading Message
   Status.style.display="none";
   //----- Display (Save/Upload button?) 
   savebtn.style.display="block";
    }

    /*-------Reading File.... 
     Display a message or loading gif for large images to be processed?
 */
    Status.innerHTML="Loading...";
 Status.style.display="block";
 savebtn.style.display="none";
    reader.readAsDataURL(img.files[0]);
    }
}else{
/*----User file input not accepted (File isn't jpg/gif/png/jpeg)
Empty the input element and set the background to default.
*/
Status.innerHTML="Format not accepted";
Status.style.display="block";
savebtn.style.display="none";
SetBG.background='white';
document.getElementById('BackgroundImage').value='';
}
}
#Status{display:none;background:white;color:black;font-size:16pt;}
#savebtn{display:none;}
<div id="Status"></div>
<input type="file" id="BackgroundImage" onchange="MyFunction()"/>
<button id="savebtn" onclick="alert('Now upload the image');">Upload and save</button>

I hope this helps. Happy coding!

NewToJS
  • 2,664
  • 3
  • 12
  • 22
  • Cheers, mate.. I did understand it all (I'm not a total noob with JavaScript) and modified it a bit to serve my purposes :) – Cooper Mar 11 '15 at 12:26
0

This may help you
let assume your browse button's id is bg-cover-file and the id of the image tag where you want to display the image preview_image

  $(document).on("change", "#bg-cover-file", function(event)
  {
     if (this.files && this.files[0])
     {
        var reader = new FileReader();

        reader.onload = function (e)
        {
            $('#preview_image').attr('src', e.target.result);
        }

        reader.readAsDataURL(this.files[0]);
     }    
   });
Shaiful Islam
  • 6,448
  • 12
  • 35
  • 54
  • Thanks, it did help me a bit. However now, when user tries to upload something else than an image, it still tries to preview it and I'll get an broken image. Is there a way to validate that the previewed image is actually image file? – Cooper Mar 10 '15 at 14:46
  • Do not call the ajax function on change of `bg-cover-file` – Shaiful Islam Mar 11 '15 at 00:42
0

function MyFunction() {
var img=document.getElementById('BackgroundImage');
var Status=document.getElementById('Status');
var savebtn=document.getElementById('savebtn');
/* SetBG will target the body tag of the web page.
You can change this to any element - 
var SetBG=document.getElementById('YourID').style;
*/
var SetBG=document.body.style;
//Split the image name
var fileExt=img.value.split('.');
//Use the last array from the split and put to lowercase 
var fileformat=fileExt[fileExt.length -1].toLowerCase();
// Check the file extension (Image formats only!)
if((fileformat==='jpg')||(fileformat==='gif')||(fileformat==='png')||(fileformat==='jpeg')) {    
    if (img.files && img.files[0]) {
    var reader = new FileReader();
    reader.onload = function (e) {
    //----Image is ready for preview.
    SetBG.background='url('+e.target.result+') no-repeat center center fixed';
    /*---- Optional, Set background as cover ---*/
    SetBG.backgroundSize="cover";
 SetBG.OBackgroundSize="cover";
 SetBG.webkitBackgroundSize="cover";
    //--Hide Loading Message
   Status.style.display="none";
   //----- Display (Save/Upload button?) 
   savebtn.style.display="block";
    }

    /*-------Reading File.... 
     Display a message or loading gif for large images to be processed?
 */
    Status.innerHTML="Loading...";
 Status.style.display="block";
 savebtn.style.display="none";
    reader.readAsDataURL(img.files[0]);
    }
}else{
/*----User file input not accepted (File isn't jpg/gif/png/jpeg)
Empty the input element and set the background to default.
*/
Status.innerHTML="Format not accepted";
Status.style.display="block";
savebtn.style.display="none";
SetBG.background='white';
document.getElementById('BackgroundImage').value='';
}
}
#Status{display:none;background:white;color:black;font-size:16pt;}
#savebtn{display:none;}
<div id="Status"></div>
<input type="file" id="BackgroundImage" onchange="MyFunction()"/>
<button id="savebtn" onclick="alert('Now upload the image');">Upload and save</button>
user25775
  • 65
  • 1
  • 10