javascript - manejo - mostrar loading mientras carga pagina jquery




¿Cómo puedo subir archivos de forma asíncrona? (20)

Actualización 2017: todavía depende de los navegadores que usa tu demográfico.

Una cosa importante que se debe entender con el "nuevo" API de file HTML5 es que no se admite hasta IE 10 . Si el mercado específico al que está apuntando tiene una prepensidad superior a la media hacia versiones anteriores de Windows, es posible que no tenga acceso a él.

A partir de 2017, aproximadamente el 5% de los navegadores son uno de IE 6, 7, 8 o 9. Si se dirige a una gran corporación (por ejemplo, esta es una herramienta B2B, o algo que está entregando para capacitación) ese número puede dispararse. Hace solo unos meses, en 2016, traté con una compañía que utiliza IE8 en más del 60% de sus máquinas.

Así que antes de hacer nada: compruebe qué navegador utilizan sus usuarios . Si no lo hace, aprenderá una lección rápida y dolorosa de por qué "funciona para mí" no es lo suficientemente bueno como para entregarlo a un cliente.

Mi respuesta de 2008 sigue.

Sin embargo, existen métodos viables que no son JS para subir archivos. Puedes crear un iframe en la página (que escondes con CSS) y luego dirigir tu formulario para que se publique en ese iframe. La página principal no necesita moverse.

Es una publicación "real", por lo que no es totalmente interactiva. Si necesita un estado, necesita algo del lado del servidor para procesarlo. Esto varía masivamente dependiendo de su servidor. ASP.NET tiene mecanismos más agradables. PHP normal falla, pero puedes usar modificaciones de Perl o Apache para evitarlo.

Si necesita múltiples cargas de archivos, es mejor hacer cada archivo de uno en uno (para superar los límites máximos de carga de archivos). Publique el primer formulario en el iframe, supervise su progreso usando lo anterior y cuando haya terminado, publique el segundo formulario en el iframe, y así sucesivamente.

O utilice una solución Java / Flash. Son mucho más flexibles en lo que pueden hacer con sus publicaciones ...

Me gustaría subir un archivo de forma asíncrona con jQuery. Este es mi HTML:

<span>File</span>
<input type="file" id="file" name="file" size="10"/>
<input id="uploadbutton" type="button" value="Upload"/>

Y aquí mi código Jquery :

$(document).ready(function () {
    $("#uploadbutton").click(function () {
        var filename = $("#file").val();

        $.ajax({
            type: "POST",
            url: "addFile.do",
            enctype: 'multipart/form-data',
            data: {
                file: filename
            },
            success: function () {
                alert("Data Uploaded: ");
            }
        });
    });
});

En lugar de cargar el archivo, solo obtengo el nombre del archivo. ¿Qué puedo hacer para solucionar este problema?

Solución actual

Estoy usando el complemento de formulario de jQuery para cargar archivos.


Aquí hay solo otra solución de cómo cargar un archivo ( sin ningún complemento )

Usando Javascripts simples y AJAX (con barra de progreso)

Parte HTML

<form id="upload_form" enctype="multipart/form-data" method="post">
    <input type="file" name="file1" id="file1"><br>
    <input type="button" value="Upload File" onclick="uploadFile()">
    <progress id="progressBar" value="0" max="100" style="width:300px;"></progress>
    <h3 id="status"></h3>
    <p id="loaded_n_total"></p>
</form>

Parte de JS

function _(el){
    return document.getElementById(el);
}
function uploadFile(){
    var file = _("file1").files[0];
    // alert(file.name+" | "+file.size+" | "+file.type);
    var formdata = new FormData();
    formdata.append("file1", file);
    var ajax = new XMLHttpRequest();
    ajax.upload.addEventListener("progress", progressHandler, false);
    ajax.addEventListener("load", completeHandler, false);
    ajax.addEventListener("error", errorHandler, false);
    ajax.addEventListener("abort", abortHandler, false);
    ajax.open("POST", "file_upload_parser.php");
    ajax.send(formdata);
}
function progressHandler(event){
    _("loaded_n_total").innerHTML = "Uploaded "+event.loaded+" bytes of "+event.total;
    var percent = (event.loaded / event.total) * 100;
    _("progressBar").value = Math.round(percent);
    _("status").innerHTML = Math.round(percent)+"% uploaded... please wait";
}
function completeHandler(event){
    _("status").innerHTML = event.target.responseText;
    _("progressBar").value = 0;
}
function errorHandler(event){
    _("status").innerHTML = "Upload Failed";
}
function abortHandler(event){
    _("status").innerHTML = "Upload Aborted";
}

Parte de PHP

<?php
$fileName = $_FILES["file1"]["name"]; // The file name
$fileTmpLoc = $_FILES["file1"]["tmp_name"]; // File in the PHP tmp folder
$fileType = $_FILES["file1"]["type"]; // The type of file it is
$fileSize = $_FILES["file1"]["size"]; // File size in bytes
$fileErrorMsg = $_FILES["file1"]["error"]; // 0 for false... and 1 for true
if (!$fileTmpLoc) { // if file not chosen
    echo "ERROR: Please browse for a file before clicking the upload button.";
    exit();
}
if(move_uploaded_file($fileTmpLoc, "test_uploads/$fileName")){ // assuming the directory name 'test_uploads'
    echo "$fileName upload is complete";
} else {
    echo "move_uploaded_file function failed";
}
?>

Aquí está la aplicación EJEMPLO


Envolviendo para futuros lectores.

Carga asíncrona de archivos

Con HTML5

Puede cargar archivos con jQuery utilizando el método $.ajax() si se admiten FormData y la API de archivos (ambas funciones HTML5).

También puede enviar archivos sin FormData, pero de cualquier manera, la API de archivos debe estar presente para procesar los archivos de manera tal que puedan enviarse con XMLHttpRequest (Ajax).

$.ajax({
  url: 'file/destination.html', 
  type: 'POST',
  data: new FormData($('#formWithFiles')[0]), // The form with the file inputs.
  processData: false,
  contentType: false                    // Using FormData, no need to process data.
}).done(function(){
  console.log("Success: Files sent!");
}).fail(function(){
  console.log("An error occurred, the files couldn't be sent!");
});

Para un ejemplo rápido y puro de JavaScript ( sin jQuery ), consulte " Enviar archivos usando un objeto FormData ".

Retroceder

Cuando HTML5 no es compatible (sin API de archivos ), la única otra solución de JavaScript puro (sin Flash o cualquier otro complemento del navegador) es la técnica de iframe oculto , que permite emular una solicitud asíncrona sin usar el objeto XMLHttpRequest .

Consiste en establecer un iframe como el destino del formulario con las entradas del archivo. Cuando el usuario envía, se realiza una solicitud y los archivos se cargan, pero la respuesta se muestra dentro del iframe en lugar de volver a renderizar la página principal. La ocultación del iframe hace que todo el proceso sea transparente para el usuario y emula una solicitud asíncrona.

Si se hace correctamente, debería funcionar virtualmente en cualquier navegador, pero tiene algunas advertencias sobre cómo obtener la respuesta del iframe.

En este caso, es posible que prefiera utilizar un complemento de envoltorio como Bifröst que use la técnica de iframe pero que también proporcione un transporte jQuery Ajax que le permita enviar archivos con solo el método $.ajax() esta manera:

$.ajax({
  url: 'file/destination.html', 
  type: 'POST',
  // Set the transport to use (iframe means to use Bifröst)
  // and the expected data type (json in this case).
  dataType: 'iframe json',                                
  fileInputs: $('input[type="file"]'),  // The file inputs containing the files to send.
  data: { msg: 'Some extra data you might need.'}
}).done(function(){
  console.log("Success: Files sent!");
}).fail(function(){
  console.log("An error occurred, the files couldn't be sent!");
});

Complementos

Bifröst es solo un pequeño envoltorio que agrega soporte de respaldo al método ajax de jQuery, pero muchos de los complementos mencionados anteriormente como jQuery Form Plugin o jQuery File Upload incluyen toda la pila de HTML5 a diferentes fallbacks y algunas características útiles para facilitar el proceso. Dependiendo de sus necesidades y requisitos, es posible que desee considerar una implementación simple o cualquiera de estos complementos.


Este complemento de jQuery de carga de archivos AJAX carga el archivo en algún lugar y pasa la respuesta a una devolución de llamada, nada más.

  • No depende de HTML específico, solo dele un <input type="file">
  • No requiere que su servidor responda de ninguna manera particular
  • No importa cuántos archivos use, o dónde estén en la página.

- Usar tan poco como -

$('#one-specific-file').ajaxfileupload({
  'action': '/upload.php'
});

- o tanto como -

$('input[type="file"]').ajaxfileupload({
  'action': '/upload.php',
  'params': {
    'extra': 'info'
  },
  'onComplete': function(response) {
    console.log('custom handler for file:');
    alert(JSON.stringify(response));
  },
  'onStart': function() {
    if(weWantedTo) return false; // cancels upload
  },
  'onCancel': function() {
    console.log('no file selected');
  }
});

He estado usando el siguiente script para cargar imágenes que funcionan bien.

HTML

<input id="file" type="file" name="file"/>
<div id="response"></div>

JavaScript

jQuery('document').ready(function(){
    var input = document.getElementById("file");
    var formdata = false;
    if (window.FormData) {
        formdata = new FormData();
    }
    input.addEventListener("change", function (evt) {
        var i = 0, len = this.files.length, img, reader, file;

        for ( ; i < len; i++ ) {
            file = this.files[i];

            if (!!file.type.match(/image.*/)) {
                if ( window.FileReader ) {
                    reader = new FileReader();
                    reader.onloadend = function (e) {
                        //showUploadedItem(e.target.result, file.fileName);
                    };
                    reader.readAsDataURL(file);
                }

                if (formdata) {
                    formdata.append("image", file);
                    formdata.append("extra",'extra-data');
                }

                if (formdata) {
                    jQuery('div#response').html('<br /><img src="ajax-loader.gif"/>');

                    jQuery.ajax({
                        url: "upload.php",
                        type: "POST",
                        data: formdata,
                        processData: false,
                        contentType: false,
                        success: function (res) {
                         jQuery('div#response').html("Successfully uploaded");
                        }
                    });
                }
            }
            else
            {
                alert('Not a vaild image!');
            }
        }

    }, false);
});

Explicación

Uso div respuesta para mostrar la animación de carga y la respuesta después de que se haya cargado.

La mejor parte es que puede enviar datos adicionales, como identificadores y etc., con el archivo cuando use este script. Lo he mencionado extra-data como en el guión.

En el nivel de PHP, esto funcionará como carga de archivos normal. Los datos extra se pueden recuperar como datos $_POST .

Aquí no estás usando un plugin y esas cosas. Puedes cambiar el código que quieras. Usted no está codificando a ciegas aquí. Esta es la funcionalidad principal de cualquier carga de archivos jQuery. En realidad Javascript.


La forma más sencilla y sólida en que lo he hecho en el pasado, es simplemente apuntar una etiqueta iFrame oculta con su formulario, luego se enviará dentro del iframe sin volver a cargar la página.

Es decir, si no desea utilizar un complemento, JavaScript o cualquier otra forma de "magia" que no sea HTML. Por supuesto que puedes combinar esto con JavaScript o lo que tengas ...

<form target="iframe" action="" method="post" enctype="multipart/form-data">
    <input name="file" type="file" />
    <input type="button" value="Upload" />
</form>

<iframe name="iframe" id="iframe" style="display:none" ></iframe>

También puede leer el contenido del iframe onLoad para los errores del servidor o las respuestas exitosas y luego onLoad al usuario.

Chrome, iFrames y onLoad

-nota- solo debe seguir leyendo si está interesado en cómo configurar un bloqueador de UI al realizar la carga / descarga

Actualmente, Chrome no activa el evento onLoad para el iframe cuando se utiliza para transferir archivos. Firefox, IE y Edge activan el evento onload para transferencias de archivos.

La única solución que encontré que funciona para Chrome era usar una cookie.

Para hacer eso básicamente cuando se inicia la carga / descarga:

  • [Cliente] Comenzar un intervalo para buscar la existencia de una cookie
  • [Server Side] Haga lo que necesite con los datos del archivo
  • [Server Side] Configurar cookie para el intervalo del lado del cliente
  • [Client Side] Interval ve la cookie y la usa como el evento onLoad. Por ejemplo, puede iniciar un bloqueador de la interfaz de usuario y luego onLoad (o cuando se crea una cookie) se elimina el bloqueador de la interfaz de usuario.

Usar una cookie para esto es feo pero funciona.

Hice un complemento de jQuery para manejar este problema para Chrome al descargar, lo puedes encontrar aquí

https://github.com/ArtisticPhoenix/jQuery-Plugins/blob/master/iDownloader.js

El mismo principio básico se aplica a la carga, también.

Para usar el descargador (incluir el JS, obviamente)

 $('body').iDownloader({
     "onComplete" : function(){
          $('#uiBlocker').css('display', 'none'); //hide ui blocker on complete
     }
 });

 $('somebuttion').click( function(){
      $('#uiBlocker').css('display', 'block'); //block the UI
      $('body').iDownloader('download', 'htttp://example.com/location/of/download');
 });

Y en el lado del servidor, justo antes de transferir los datos del archivo, cree la cookie

 setcookie('iDownloader', true, time() + 30, "/");

El complemento verá la cookie y luego activará la onComplete llamada onComplete .


Nota: esta respuesta no está actualizada, ahora es posible cargar archivos con XHR.

No puede cargar archivos utilizando XMLHttpRequest (Ajax). Puedes simular el efecto usando un iframe o Flash. El excelente complemento de jQuery Form que publica sus archivos a través de un iframe para obtener el efecto.


Puedes hacerlo en JavaScript de vainilla con bastante facilidad. Aquí hay un fragmento de mi proyecto actual:

var xhr = new XMLHttpRequest();
xhr.upload.onprogress = function(e) {
    var percent = (e.position/ e.totalSize);
    // Render a pretty progress bar
};
xhr.onreadystatechange = function(e) {
    if(this.readyState === 4) {
        // Handle file upload complete
    }
};
xhr.open('POST', '/upload', true);
xhr.setRequestHeader('X-FileName',file.name); // Pass the filename along
xhr.send(file);

Puedes usar

$(function() {
    $("#file_upload_1").uploadify({
        height        : 30,
        swf           : '/uploadify/uploadify.swf',
        uploader      : '/uploadify/uploadify.php',
        width         : 120
    });
});

Demo


Recomiendo usar el plugin Fine Uploader para este propósito. Su código de JavaScript sería:

$(document).ready(function() {
  $("#uploadbutton").jsupload({
    action: "addFile.do",
    onComplete: function(response){
      alert( "server response: " + response);
    }
  });
});

Una solución que encontré fue que la <form> apunte a un iFrame oculto. El iFrame puede ejecutar JS para mostrar al usuario que está completo (en la carga de la página).


jQuery Uploadify es otro complemento bueno que he usado antes para cargar archivos. El código de JavaScript es tan simple como el siguiente: código. Sin embargo, la nueva versión no funciona en Internet Explorer.

$('#file_upload').uploadify({
    'swf': '/public/js/uploadify.swf',
    'uploader': '/Upload.ashx?formGuid=' + $('#formGuid').val(),
    'cancelImg': '/public/images/uploadify-cancel.png',
    'multi': true,
    'onQueueComplete': function (queueData) {
        // ...
    },
    'onUploadStart': function (file) {
        // ...
    }
});

He realizado muchas búsquedas y he llegado a otra solución para cargar archivos sin ningún complemento y solo con ajax. La solución es la siguiente:

$(document).ready(function () {
    $('#btn_Upload').live('click', AjaxFileUpload);
});

function AjaxFileUpload() {
    var fileInput = document.getElementById("#Uploader");
    var file = fileInput.files[0];
    var fd = new FormData();
    fd.append("files", file);
    var xhr = new XMLHttpRequest();
    xhr.open("POST", 'Uploader.ashx');
    xhr.onreadystatechange = function () {
        if (xhr.readyState == 4) {
             alert('success');
        }
        else if (uploadResult == 'success')
            alert('error');
    };
    xhr.send(fd);
}

Es una pregunta antigua, pero todavía no tiene una respuesta correcta, así que:

¿Has probado jQuery-File-Upload ?

Aquí hay un ejemplo del enlace anterior -> jQuery-File-Upload que podría resolver su problema:

$('#fileupload').fileupload({
    add: function (e, data) {
        var that = this;
        $.getJSON('/example/url', function (result) {
            data.formData = result; // e.g. {id: 123}
            $.blueimp.fileupload.prototype
                .options.add.call(that, e, data);
        });
    } 
});

Esta es mi solución.

<form enctype="multipart/form-data">    

    <div class="form-group">
        <label class="control-label col-md-2" for="apta_Description">Description</label>
        <div class="col-md-10">
            <input class="form-control text-box single-line" id="apta_Description" name="apta_Description" type="text" value="">
        </div>
    </div>

    <input name="file" type="file" />
    <input type="button" value="Upload" />
</form>

y los js

<script>

    $(':button').click(function () {
        var formData = new FormData($('form')[0]);
        $.ajax({
            url: '@Url.Action("Save", "Home")',  
            type: 'POST',                
            success: completeHandler,
            data: formData,
            cache: false,
            contentType: false,
            processData: false
        });
    });    

    function completeHandler() {
        alert(":)");
    }    
</script>

Controlador

[HttpPost]
public ActionResult Save(string apta_Description, HttpPostedFileBase file)
{
    return Json(":)");
}

Busque Manejar el proceso de carga de un archivo, de forma asincrónica aquí: https://developer.mozilla.org/en-US/docs/Using_files_from_web_applications

Muestra del enlace.

<?php
if (isset($_FILES['myFile'])) {
    // Example:
    move_uploaded_file($_FILES['myFile']['tmp_name'], "uploads/" . $_FILES['myFile']['name']);
    exit;
}
?><!DOCTYPE html>
<html>
<head>
    <title>dnd binary upload</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <script type="text/javascript">
        function sendFile(file) {
            var uri = "/index.php";
            var xhr = new XMLHttpRequest();
            var fd = new FormData();

            xhr.open("POST", uri, true);
            xhr.onreadystatechange = function() {
                if (xhr.readyState == 4 && xhr.status == 200) {
                    // Handle response.
                    alert(xhr.responseText); // handle response.
                }
            };
            fd.append('myFile', file);
            // Initiate a multipart/form-data upload
            xhr.send(fd);
        }

        window.onload = function() {
            var dropzone = document.getElementById("dropzone");
            dropzone.ondragover = dropzone.ondragenter = function(event) {
                event.stopPropagation();
                event.preventDefault();
            }

            dropzone.ondrop = function(event) {
                event.stopPropagation();
                event.preventDefault();

                var filesArray = event.dataTransfer.files;
                for (var i=0; i<filesArray.length; i++) {
                    sendFile(filesArray[i]);
                }
            }
        }
    </script>
</head>
<body>
    <div>
        <div id="dropzone" style="margin:30px; width:500px; height:300px; border:1px dotted grey;">Drag & drop your file here...</div>
    </div>
</body>
</html>

Convierta el archivo a base64 usando | readAsDataURL() HTML5 o algún codificador base64 . Violín aquí

var reader = new FileReader();

        reader.onload = function(readerEvt) {
            var binaryString = readerEvt.target.result;
            document.getElementById("base64textarea").value = btoa(binaryString);
        };

        reader.readAsBinaryString(file);

Luego para recuperar:

window.open("data:application/octet-stream;base64," + base64);

Puede realizar las cargas asíncronas de archivos múltiples mediante JavaScript o jQuery y sin necesidad de utilizar ningún complemento. También puede mostrar el progreso en tiempo real de la carga de archivos en el control de progreso. Me he encontrado con 2 buenos enlaces -

  1. Característica de carga de archivos múltiples de ASP.NET basada en formularios web con barra de progreso
  2. ASP.NET MVC basado en carga de archivos múltiples hecha en jQuery

El lenguaje del lado del servidor es C #, pero puede hacer algunas modificaciones para que funcione con otro lenguaje como PHP.

Carga de archivos ASP.NET Core MVC:

En la vista crear control de carga de archivos en html:

<form method="post" asp-action="Add" enctype="multipart/form-data">
    <input type="file" multiple name="mediaUpload" />
    <button type="submit">Submit</button>
</form>

Ahora crea un método de acción en tu controlador:

[HttpPost]
public async Task<IActionResult> Add(IFormFile[] mediaUpload)
{
    //looping through all the files
    foreach (IFormFile file in mediaUpload)
    {
        //saving the files
        string path = Path.Combine(hostingEnvironment.WebRootPath, "some-folder-path"); 
        using (var stream = new FileStream(path, FileMode.Create))
        {
            await file.CopyToAsync(stream);
        }
    }
}

La variable hostingEnvironment es de tipo IHostingEnvironment que se puede inyectar al controlador utilizando la inyección de dependencia, como:

private IHostingEnvironment hostingEnvironment;
public MediaController(IHostingEnvironment environment)
{
    hostingEnvironment = environment;
}

Puede ver una solución resuelta con una demostración de trabajo here que le permite obtener una vista previa y enviar archivos de formulario al servidor. Para su caso, necesita usar Ajax para facilitar la carga del archivo al servidor:

<from action="" id="formContent" method="post" enctype="multipart/form-data">
    <span>File</span>
    <input type="file" id="file" name="file" size="10"/>
    <input id="uploadbutton" type="button" value="Upload"/>
</form>

Los datos que se envían son un formdata. En su jQuery, use una función de envío de formulario en lugar de hacer clic en un botón para enviar el archivo de formulario como se muestra a continuación.

$(document).ready(function () {
   $("#formContent").submit(function(e){

     e.preventDefault();
     var formdata = new FormData(this);

 $.ajax({
     url: "ajax_upload_image.php",
     type: "POST",
     data: formdata,
     mimeTypes:"multipart/form-data",
     contentType: false,
     cache: false,
     processData: false,
     success: function(){

     alert("successfully submitted");

     });
   });
});

here


Un enfoque moderno sin Jquery es usar el objeto FileList del <input type="file">cual el usuario selecciona un archivo (s) y luego usar Fetch para publicar el FileList envuelto en un objeto FormData .

// The input DOM element
const inputElement = document.querySelector('input');

// Listen for a file submit from user
inputElement.addEventListener('change', () => {
    const data = new FormData()
    data.append('file', inputElement.files[0])
    data.append('imageName', 'flower')

    // Post to server
    fetch('/uploadImage', {
        method: 'POST',
        body: data
    })
});

Usar HTML5 y JavaScript , cargar asíncrono es bastante fácil, creo la lógica de carga junto con su html, esto no funciona completamente ya que necesita la API, pero demuestra cómo funciona, si tiene el punto final llamado /uploaddesde la raíz de su sitio web Este código debería funcionar para usted:

const asyncFileUpload = () => {
  const fileInput = document.getElementById("file");
  const file = fileInput.files[0];
  const uri = "/upload";
  const xhr = new XMLHttpRequest();
  xhr.upload.onprogress = e => {
    const percentage = e.loaded / e.total;
    console.log(percentage);
  };
  xhr.onreadystatechange = e => {
    if (xhr.readyState === 4 && xhr.status === 200) {
      console.log("file uploaded");
    }
  };
  xhr.open("POST", uri, true);
  xhr.setRequestHeader("X-FileName", file.name);
  xhr.send(file);
}
<form>
  <span>File</span>
  <input type="file" id="file" name="file" size="10" />
  <input onclick="asyncFileUpload()" id="upload" type="button" value="Upload" />
</form>

También más información sobre XMLHttpReques:

El objeto XMLHttpRequest

Todos los navegadores modernos soportan el objeto XMLHttpRequest. El objeto XMLHttpRequest se puede utilizar para intercambiar datos con un servidor web entre bastidores. Esto significa que es posible actualizar partes de una página web, sin volver a cargar toda la página.


Crear un objeto XMLHttpRequest

Todos los navegadores modernos (Chrome, Firefox, IE7 +, Edge, Safari, Opera) tienen un objeto XMLHttpRequest incorporado.

Sintaxis para crear un objeto XMLHttpRequest:

variable = new XMLHttpRequest ();


Acceso a través de dominios

Por razones de seguridad, los navegadores modernos no permiten el acceso entre dominios.

Esto significa que tanto la página web como el archivo XML que intenta cargar, deben estar ubicados en el mismo servidor.

Todos los ejemplos en W3Schools abren archivos XML ubicados en el dominio W3Schools.

Si desea utilizar el ejemplo anterior en una de sus propias páginas web, los archivos XML que cargue deben estar ubicados en su propio servidor.

Para más detalles, puedes seguir leyendo here ...





upload