entre Desarrolladores

Recibe ayuda de expertos

Registrate y pregunta

Es gratis y fácil

Recibe respuestas

Respuestas, votos y comentarios

Vota y selecciona respuestas

Recibe puntos, vota y da la solución

Pregunta

1voto

Subir Foto con Ajax>JQuery y CodeIgniter

Hola, tengo una vista sencilla de prueba en CodeIgniter y en esta tengo un campo input=file quiero que cuando se presione "Guardar" a través de AJAX este conecte a un controlador de CodeIgniter que guarde el fichero en el servidor.
Saludos Dairon:
Código HTML:

 <div class="container">
        <div class="row">
            <div class="form-group col-lg-10">
                <div class="col-lg-12" id="foto-portada">                                                               
                    <h4>Foto de Portada</h4>
                    <div id="preview" class="thumbnail">
                        <a href="#" class="btn btn-default" id="file-select">Elegir Archivo</a>
                        <img src="<?php echo base_url() ?>images/thumbs.PNG" alt="">
                    </div>
                    <span class="alert alert-info" id="file-info">No hay Archivo</span>
                    <input type="file" name="file" id="file">                                     
                    <a href="#" class="btn btn-primary" id="file-save">Guardar</a>
                </div> 
            </div>
        </div>
    </div>

Código JS:

$(document).ready(function() {
    $('#preview').hover(function() {
            $(this).find("#file-select").fadeIn("fast");
                }, function() {
            $(this).find("#file-select").fadeOut("fast");
        });
    $('input[type=file]').change(function() {
            var file = (this.files[0].name).toString();
            var reader = new FileReader();

            $('#file-info').text('');
            $('#file-info').text(file);

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

            reader.readAsDataURL(this.files[0]);
        });
});
$(document).on('click', '#file-select', (function(e) {
    e.preventDefault();
    $('#file').click();
}));

Estilo CSS:

#foto-portada{
  width: 300px;
  margin: 10px auto;
  text-align: center;
} 
#preview{
  width: 171px;
  margin: 0 auto;
  margin-bottom: 10px;
  position: relative;
}
#preview a{
  position: absolute;
  bottom: 5px;
  left: 5px;
  right: 5px;
  display: none;
}
#file-info{
  display: block;
}
input[type=file]{
  position: absolute;
  visibility: hidden;
  width: 0;
  z-index: -9999;
}
#file-save{
  width: 171px;
}

1 Respuesta

3votos

white Puntos75880

para lo que requieres necesitas de formData, aca te dejo un clase que defini como "portrait_uploader" como ejemplo:

Javascript:

var portrait_uploader = {

    reader : null,
    form_data : null,
    file_data : null,
    callbacks : {
        progress : false,
        loaded : false,
        uploaded : false,
        error : false
    },

    init : function()
    {
        this.reader = new FileReader();
        this.form_data = new FormData();

        this.handle_file_upload();

        return this;
    },

    on : function(type, callback)
    {
        var _undefined;

        if(this.callbacks[type] === _undefined || typeof callback !== 'function')
            return this;

        portrait_uploader.callbacks[type] = callback;

        return this;
    },

    upload_file : function(submit_btn)
    {
        this.file_data = $('#file').prop('files')[0];

        this.form_data.append('portrait', this.file_data);

        $.ajax({
            url: global_data.portrait_upload_url,
            dataType: 'json',
            cache: false,
            contentType: false,
            processData: false,
            data: portrait_uploader.form_data,                         
            type: 'post',
            xhr: function()
            {
                var xhr = $.ajaxSettings.xhr();

                if(xhr.upload)
                {                   
                    xhr.upload.addEventListener(
                        'progress',
                        portrait_uploader.handle_progress,
                        false
                    );
                }

                return xhr;
            },
            complete : function(data)
            {
                if(portrait_uploader.callbacks.loaded)
                    portrait_uploader.callbacks.loaded.call(null, data);
            },
            success : function(data)
            {
                if(data.error)
                {
                    if(portrait_uploader.callbacks.error)
                        portrait_uploader.callbacks.error.call(null, data.error, data);

                    return false;
                }

                if(portrait_uploader.callbacks.uploaded)
                    portrait_uploader.callbacks.uploaded.call(null, data);
            },
            error : function(data)
            {
                if(portrait_uploader.callbacks.error)
                    portrait_uploader.callbacks.error.call(null, '404 not found', data);
            }
        })

        return false; // prevent anchor action
    },

    handle_progress : function(event)
    {
        console.log('loading');

        if (event.lengthComputable)
        {

            var percentage = (event.loaded / event.total) * 100;

            if(portrait_uploader.callbacks.progress)
                portrait_uploader.callbacks.progress.call(null, percentage, this.file_data);

        }
    },

    handle_file_upload : function()
    {
        $('#file').change(function() {

            var file = (this.files[0].name).toString();

            $('#file-info').empty().text(file);

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

            portrait_uploader.reader.readAsDataURL(this.files[0]);
        });

        $('#file-save').on('click', null, {
            reader : this.reader
        }, function(){
            return portrait_uploader.upload_file(this);
        });
    }

};

$(document).ready(function() {

    $('#preview').on('mouseenter mouseleave', null, {can_animate : true}, function(event) {

        var desired_event = {
            mouseleave  : 'fadeOut',
            mouseenter  : 'fadeIn'
        };

        event.data.can_animate = false;

        $("#file-select").stop(true, true)[desired_event[event.type]]("fast", function(){
            event.data.can_animate = true;
        });

    });

    $('#file-select').on('click', function(e) {
        e.preventDefault();
        $('#file').click();
    });

    $('#file').val(null);

    portrait_uploader
        .init()
        .on('progress', function(percentage){
            // en este evento obtenemos el porcentaje de subida C:

            console.log('progreso: ', percentage);
        })
        .on('uploaded', function(data){
            // el archivo se subió
            // tomamos medidas aqui C:
        })
        .on('error', function(msg, data){

            // ocurrio un error
            $('#upload_errors')
                .modal('show')
                .find('.upload_errors')
                .html(msg);
        });

});

cambia los callbacks que defini por los que tu desees:

Javascript:

portrait_uploader
    .init()
    .on('progress', function(percentage){
        // en este evento obtenemos el porcentaje de subida C:

        console.log('progreso: ', percentage);
    })
    .on('uploaded', function(data){
        // el archivo se subió
        // tomamos medidas aqui C:
    })
    .on('error', function(msg, data){

        // ocurrio un error
        $('#upload_errors')
            .modal('show')
            .find('.upload_errors')
            .html(msg);
    });

html:

<div class="container">
    <div class="row">
        <div class="form-group col-lg-10">
            <div class="col-lg-12" id="foto-portada">                                                               
                <h4>Foto de Portada</h4>
                <div id="preview" class="thumbnail" style="position: relative">
                    <a href="#" class="btn btn-default" id="file-select">Elegir Archivo</a>
                    <img src="https://placekitten.com/g/900/350" alt="">
                </div>
                <span class="alert alert-info" id="file-info">No hay Archivo</span>
                <input type="file" name="portrait" id="file">
                <a href="#" class="btn btn-primary" id="file-save">Guardar</a>
            </div>
        </div>
    </div>
</div>

<div class="modal fade" id="upload_errors">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <button class="close" data-dismiss="modal" type="button"><span>×</span></button>
                <h4 class="modal-title">Error al subir la imagen</h4>
            </div>

            <div class="modal-body">
                <div class="alert alert-danger upload_errors"></div>
            </div>

            <div class="modal-footer">
                <button class="btn btn-primary" data-dismiss="modal" type="button">Aceptar</button>
            </div>
        </div>
    </div>
</div>

<script type="text/javascript">
    var global_data = {
        portrait_upload_url : '<?php echo base_url('/home/upload/') ?>'
    };
</script>

cambia portrait_upload_url : '<?php echo base_url('/home/upload/') ?>' a la url de tu controlador.


contolador:

public function upload()
{
    $config = array();
    $config["upload_path"] = APPPATH . "uploads/";
    $config["allowed_types"] = "gif|jpg|jpeg|png";
    $config["max_size"] = "2000";
    $config["remove_spaces"] = TRUE;

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

    if(!$this->upload->do_upload('portrait'))
    {
        $errors = array('error' => $this->upload->display_errors());
        die(json_encode($errors));
    }
    else
    {
        $data = array('upload_data' => $this->upload->data());
        die(json_encode(array('file' => $data['upload_data']['file_name'])));
    }
}

0voto

dairon comentado

Ahora comienso a ajustarla para ver si logró salir de esta parte y entender el código para no tener el mismo problema ;)

0voto

dairon comentado

@white tienes un nivel de JavaScript super alto, que libros o tutoriales me recomendarías para obtener un nivel parecido al tuyo ??

0voto

white comentado

realmente no es alto :P

La mejor manera de aprender es leer la documentación del lenguaje o tecnología y tener a google en las pestañas de tu navegador, gran cantidad de problemas resueltos estan en idioma inglés. libros por la red hay varios, como por ejemplo:

http://librosweb.es/libro/javascript/
http://www.etnassoft.com/biblioteca/page/2/?search_term=javascript&books_category=all&books_criteria=post_date_DESC&lang=spanish&since=all

ya perdi la cuenta de los libros que baje de la red y nunca leí, es mas equivocarse y corregir.

saludos!

0voto

dairon comentado

@white mano me devuelve error

0voto

white comentado

agrega aqui el error que te devuelve.

0voto

dairon comentado

ya el error era mio que pusel a direccion del controlador mal, pero entonces ahora me sube dos veces el mismo fichero. por cierto @white te mandé un mensaje privado

0voto

dairon comentado

Ya lo corregí, gracias por todo mano

0voto

dairon comentado

@white mano quiero que en el id="file-info" que es un span se muestre el camino completo de la imagen insertada en codeigniter para luego poder guardar el camino en la base de datos, pero he leido tú código y no encuentro como hacerlo.
Saludos Dairon

0voto

white comentado

Si lo que intentas es obtener la ruta del archivo local "C:/folder/image.png" no es posible por razones de seguridad, todo navegador moderno adopta esto. lo que puedes hacer es guardar la ruta de la imagen despues de haberse subido.

$path = FCPATH . "uploads/" . $data['upload_data']['file_name']

y para la url:

base_url('/uploads/' . $data['upload_data']['file_name']);

como sugerencia te recomiendo darle a la imagen un nombre con una serie de caracteres aleatorios, podrias usar el helper random_string() https://ellislab.com/codeigniter/user-guide/helpers/string_helper.html


PD: si lo que deseas es obtener la ruta despues de haberse subido la imagen, usa los eventos

el evento:

.on('uploaded', function(data){
    // data.url contiene la ruta de la imagen 
    $('#file-info').html(data.url);
})

y en el controlador:

$data = array('upload_data' => $this->upload->data());

die(json_encode(array(
        'file' => $data['upload_data']['file_name'],
        'url' => base_url('/uploads/' . $data['upload_data']['file_name'])
)));

0voto

dairon comentado

Funcionó a la perfección mano, 1Millon de Gracias tengo que aprender mucho aún

Por favor, accede o regístrate para responder a esta pregunta.

Otras Preguntas y Respuestas


...

Bienvenido a entre Desarrolladores, donde puedes realizar preguntas y recibir respuestas de otros miembros de la comunidad.

Conecta