Jquery - Load multi-image from input file to container

0

I would like to upload the selected images through a multiple input type = 'file' to a container in real time, that is, I select a series of images and once accepted the samples in a modal window.

Googleando I have found code, which after modification, more or less fits in what I need.

What is my problem? Well, when loading the images I have fields like file.name, which comes from a filereader object, which is not updated and always returns the last file.

I pass some screens of the process:

The HTML code I use is the following:

    <!-- IMAGES UPLOAD MODAL MENU -->

    <div class="modal fade" id="imagesUpload" tabindex="-1" role="dialog" aria-labelledby="change" aria-hidden="true">

      <div class="modal-dialog modal-lg">

           <div class="modal-content">

                <div class="modal-header">
                  <button type="button" class="close" data-dismiss="modal" aria-hidden="true"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span></button>
                  <h4 class="modal-title custom_align" id="Heading">Pujar Imatges</h3>
                </div>

                <form action="uploadImageAddcloud.php" id='formchange' method="post" enctype="multipart/form-data">

                    <div class="modal-body" id='imagesUploadContent'>
                          <output id='result'>
                    </div>

                    <div class="modal-footer ">
                        <div class="text-center">
                            <label class="custom-file-upload">
                                <input id='filesUpload' type="file" multiple/>
                                <input type="hidden" name="codigoUploadImage" value="<?php echo $codigo; ?>">
                                <input type="hidden" name="urlUploadImage" value="<?php echo $_SERVER["REQUEST_URI"]; ?>">
                                <i class="fa fa-cloud-upload"></i> Selecciona
                            </label>
                            <input class="btn btn-gral btn-tool-footer-medium btn-icon" id='btnUploadImagesCancelar' value="Cancel.lar">
                            <input type="submit" class="btn btn-gral btn-tool-footer-medium btn-icon" id='btnUploadImagesProcessar' value="Processar" style="background-color: #404040; color: white;">
                        </div>
                    </div>
              </form>
          </div>
      </div>
    </div>

And the function of Jquery is:

function handleFileSelect() {
              //Check File API support
              if (window.File && window.FileList && window.FileReader) {

                  var files = event.target.files; //FileList object
                  var output = document.getElementById("result");

                  for (var i = 0; i < files.length; i++) {

                      var file = files[i];
                      //Only pics
                      if (!file.type.match('image')) continue;

                      var picReader = new FileReader();

                      picReader.addEventListener("load", function (event) {


                          var picFile = event.target;

                          var imageBox = $("<div class='box-image-library' id='box-image-library'> \
                                               <img class='image-library' id='fileImageLibrary'/> \
                                               <div class='btn-image-library-delete'> \
                                                  <button class='btn-image-library' data-action='delete'><i class='material-icons' style='font-size: 20px'>delete</i></button> \
                                               </div> \
                                               <div class='box-text-image-library-upload'> \
                                                   <span class='text-descripcio-image-library' id='text-descripcio-image-library'></span> \
                                               </div> \
                                           </div>");

                          // Insert Element in Box Content
                          $('#imagesUploadContent').append(imageBox);

                          // Set src img, filename and modify id elements
                          $('#fileImageLibrary').attr('src', picFile.result);
                          $('#text-descripcio-image-library').text(file.name);

                          $('#fileImageLibrary').attr('id','fileImageLibrary-' + file.name );
                          $('#text-descripcio-image-library').attr('id','text-descripcio-image-library-' + file.name );
                      });

                      //Read the image
                      picReader.readAsDataURL(file);
                  }
              } else {
                  console.log("Your browser does not support File API");
              }
          }

          document.getElementById('filesUpload').addEventListener('change', handleFileSelect, false);

A little the explanation of the Jquery would be the following: it controls that there is a file type object, this has to be of the image type, if it is it creates an HTML structure based on a template to format the element's visualization. It embeds the image from img src and the description.

I would appreciate any help-guidance, thank you!

    
asked by ruzD 01.02.2018 в 12:30
source

2 answers

1

You could separate the entire operation from picReader to another function to which you only pass file , since when the event occurs load (asynchronous) the variable file has been changed because the for continued iterating and the% load had not been triggered. In other words, you pass the correct parameter event but you access an external variable that mutated while the event was resolved.

I would try with:

function appendImage(file) {
    var picReader = new FileReader();

    picReader.addEventListener("load", function(event) {

        var picFile = event.target;

        var imageBox = $("<div class='box-image-library' id='box-image-library'> \
                            <img class='image-library' id='fileImageLibrary'/> \
                            <div class='btn-image-library-delete'> \
                              <button class='btn-image-library' data-action='delete'><i class='material-icons' style='font-size: 20px'>delete</i></button> \
                            </div> \
                            <div class='box-text-image-library-upload'> \
                              <span class='text-descripcio-image-library' id='text-descripcio-image-library'></span> \
                            </div> \
                          </div>");

        // Insert Element in Box Content
        $('#imagesUploadContent').append(imageBox);

        // Set src img, filename and modify id elements
        $('#fileImageLibrary').attr('src', picFile.result);
        $('#text-descripcio-image-library').text(file.name);

        $('#fileImageLibrary').attr('id', 'fileImageLibrary-' + file.name);
        $('#text-descripcio-image-library').attr('id', 'text-descripcio-image-library-' + file.name);
    });

    //Read the image
    picReader.readAsDataURL(file);
}

function handleFileSelect() {
    //Check File API support
    if (!window.File || !window.FileList || !window.FileReader) {
        console.log("Your browser does not support File API");
        return;
    }

    var files = event.target.files; //FileList object
    var output = document.getElementById("result");

    for (var i = 0; i < files.length; i++) {

        var file = files[i];
        //Only pics
        if (!file.type.match('image')) continue;

        appendImage(file);
    }
}

document.getElementById('filesUpload').addEventListener('change', handleFileSelect, false);
    
answered by 01.02.2018 / 14:12
source
1

I do not know if you are using any component of JQuery but based on my experience I can recommend the one I used:

Fileraje de krajee

Live Demo

I give you a functional example:

$(document).on('ready', function() {
     $("#input-7").fileinput({
        uploadUrl: "Upload.php" // server upload action
        , autoReplace: true
        , showCaption: true
        , showUpload: true
        , showPreview: true
        , maxFileCount: 10
        , mainClass: "input-group-lg"
        , allowedPreviewTypes: ['text', 'image']   
        , uploadExtraData: function () {  // callback example      
        
            var documentos = [];
            
            $.each($(this)[0].filenames, function (i, v) {
                var nombre = v;
                //Busco la extension
                var lastPoint = nombre.lastIndexOf(".");
                var extension = nombre.substring(lastPoint + 1);

                var b;
                switch (extension.toUpperCase()) {
                    case "ZIP":
                    case "RAR":
                    case "JPG":
                    case "PNG":
                    case "JPEG":
                        b = {
                            'id': i + 1,
                            'nombre': nombre,
                            'mensaje': '',
                            'tipo': extension.toUpperCase(),
                            'procesado': false
                        };
                        documentos.push(b);
                        break;

                    case "PDF":
                        b = {
                            'id': i + 1,
                            'nombre': nombre,
                            'mensaje': '',
                            'tipo': extension.toUpperCase(),
                            'procesado': false
                        };
                        pdf.push(b);
                        documentos.push(b);
                        break;
                    case "XML":
                        b = {
                            'id': i + 1,
                            'nombre': nombre,
                            'mensaje': '',
                            'tipo': extension.toUpperCase(),
                            'procesado': false
                        };
                        xml.push(b);
                        documentos.push(b);
                        break;
                    default:
                        b = {
                            'id': i + 1,
                            'nombre': nombre,
                            'mensaje': msgWrongFileType,
                            'tipo': extension.toUpperCase(),
                            'procesado': false
                        };
                        documentos.push(b);
                        break;
                }
            });

            //Recorro todos los xmls y pdfs, los que no tenga par se marcaran como bad
            $.each(xml, function (i, v) {
                if (v.tienePar == false) {
                    v.mensaje = msgNoPdf;
                    //bad.push(v);
                }
            });


            var data = {
                Documentos: documentos
                , DatoExtra: "Informacion EXTRA"
            }

            alert(JSON.stringify(data));
            return { datos: JSON.stringify(data) }; //Este objeto mandarias al SERVER al presionar upload
          }
        });
        
        
});

$('#input-7').on('filebatchpreupload', function (event, data) {
    //Si quieres que haga algo antes de enviar la informacion
    $("#divResult").text("Enviando...");
});

//Para procesar los archivos despues de haberlos subido
$('#input-7').on('filebatchuploadsuccess', function (event, data) {
    var response = data.response;
    $("#divResult").text("Procesados...");
    //Despues de procesare la informacion el server respondera con esto... puedes decidir que hacer.. ya se mostrar un mensaje al usuairo
});

$('#input-7').on('filecleared', function () {
    //Si queires que haga algo al limpiar los archivos
    alert('0 archivos');
});
.box{
    background-color: #fff;
    border: 1px solid #ddd;
    -webkit-border-top-left-radius: 4px;
    -webkit-border-top-right-radius: 4px;
    -moz-border-radius-topleft: 4px;
    -moz-border-radius-topright: 4px;
    border-top-left-radius: 4px;
    border-top-right-radius: 4px;
    margin: 15px 0;
    padding: 39px 19px 14px;
    position: relative;
    }
<!-- bootstrap 4.x is supported. You can also use the bootstrap css 3.3.x versions -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css">
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-fileinput/4.4.5/css/fileinput.min.css" media="all" rel="stylesheet" type="text/css" />
<!-- if using RTL (Right-To-Left) orientation, load the RTL CSS file after fileinput.css by uncommenting below -->
<!-- link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-fileinput/4.4.5/css/fileinput-rtl.min.css" media="all" rel="stylesheet" type="text/css" /-->
<!-- optionally uncomment line below if using a theme or icon set like font awesome (note that default icons used are glyphicons and 'fa' theme can override it) -->
<!-- link https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css media="all" rel="stylesheet" type="text/css" /-->
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<!-- sortable.min.js is only needed if you wish to sort / rearrange files in initial preview. 
    This must be loaded before fileinput.min.js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-fileinput/4.4.5/js/plugins/sortable.min.js" type="text/javascript"></script>
<!-- purify.min.js is only needed if you wish to purify HTML content in your preview for 
    HTML files. This must be loaded before fileinput.min.js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-fileinput/4.4.5/js/plugins/purify.min.js" type="text/javascript"></script>
<!-- popper.min.js below is needed if you use bootstrap 4.x. You can also use the bootstrap js 
   3.3.x versions without popper.min.js. -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.11.0/umd/popper.min.js"></script>
<!-- bootstrap.min.js below is needed if you wish to zoom and preview file content in a detail modal
    dialog. bootstrap 4.x is supported. You can also use the bootstrap js 3.3.x versions. -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/js/bootstrap.min.js" type="text/javascript"></script>
<!-- the main fileinput plugin file -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-fileinput/4.4.5/js/fileinput.min.js"></script>
<!-- optionally uncomment line below for loading your theme assets for a theme like Font Awesome ('fa') -->
<!-- script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-fileinput/4.4.5/themes/fa/theme.min.js"></script -->


<div id="divResult" class="box">

<div/>
<div class="box">

<input id="input-7" name="input7[]" multiple type="file" class="file"   data-allowed-file-extensions='["xml","pdf","zip","rar","jpg","jpeg","png","gif"]' />

<div/>

And more or less something like this you should do in PHP:

League of the full PHP example

// upload.php
// 'images' refers to your file input name attribute
if (empty($_FILES['images'])) {
    echo json_encode(['error'=>'No files found for upload.']); 
    // or you can throw an exception 
    return; // terminate
}

// get the files posted
$images = $_FILES['images'];

// get user id posted
$userid = empty($_POST['userid']) ? '' : $_POST['userid'];

// get user name posted
$username = empty($_POST['username']) ? '' : $_POST['username'];

// a flag to see if everything is ok
$success = null;

// file paths to store
$paths= [];

// get file names
$filenames = $images['name'];

// loop and process files
for($i=0; $i < count($filenames); $i++){
    $ext = explode('.', basename($filenames[$i]));
    $target = "uploads" . DIRECTORY_SEPARATOR . md5(uniqid()) . "." . array_pop($ext);
    if(move_uploaded_file($images['tmp_name'][$i], $target)) {
        $success = true;
        $paths[] = $target;
    } else {
        $success = false;
        break;
    }
}

// check and process based on successful status 
if ($success === true) {
    // call the function to save all data to database
    // code for the following function 'save_data' is not 
    // mentioned in this example
    save_data($userid, $username, $paths);

    // store a successful response (default at least an empty array). You
    // could return any additional response info you need to the plugin for
    // advanced implementations.
    $output = [];
    // for example you can get the list of files uploaded this way
    // $output = ['uploaded' => $paths];
} elseif ($success === false) {
    $output = ['error'=>'Error while uploading images. Contact the system administrator'];
    // delete any uploaded files
    foreach ($paths as $file) {
        unlink($file);
    }
} else {
    $output = ['error'=>'No files were processed.'];
}

// return a json encoded response for plugin to process successfully
echo json_encode($output);

I hope somehow this example helps you, whether you decide to use it or not.

    
answered by 01.02.2018 в 14:48