javascript with Como posso carregar arquivos de forma assíncrona?




upload file to server jquery (24)

var formData=new FormData();
formData.append("fieldname","value");
formData.append("image",$('[name="filename"]')[0].files[0]);

$.ajax({
    url:"page.php",
    data:formData,
    type: 'POST',
    dataType:"JSON",
    cache: false,
    contentType: false,
    processData: false,
    success:function(data){ }
});

Você pode usar dados de formulário para postar todos os seus valores, incluindo imagens.

Eu gostaria de fazer upload de um arquivo de forma assíncrona com jQuery. Este é meu HTML:

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

E aqui meu 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: ");
            }
        });
    });
});

Em vez do arquivo que está sendo carregado, estou recebendo apenas o nome do arquivo. O que posso fazer para corrigir este problema?

Solução Atual

Eu estou usando o jQuery Form Plugin para fazer upload de arquivos.


Converte o arquivo para base64 usando o readAsDataURL() ou algum codificador de base64 do HTML5 . Violino aqui

var reader = new FileReader();

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

        reader.readAsBinaryString(file);

Então, para recuperar:

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

jQuery Uploadify é outro bom plugin que eu usei antes para fazer upload de arquivos. O código JavaScript é tão simples quanto o seguinte: código. No entanto, a nova versão não funciona no 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) {
        // ...
    }
});

Eu fiz muita pesquisa e cheguei a outra solução para fazer upload de arquivos sem qualquer plugin e apenas com ajax. A solução é como abaixo:

$(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);
}

Atualização de 2017: ainda depende dos navegadores usados ​​pelos usuários.

Uma coisa importante para entender com a "nova" API do file HTML5 é que ela não é suportada até o IE 10 . Se o mercado específico que você está mirando tem uma preponderância acima da média em relação às versões mais antigas do Windows, talvez você não tenha acesso a ele.

Em 2017, cerca de 5% dos navegadores são do IE 6, 7, 8 ou 9. Se você se depara com uma grande corporação (por exemplo, uma ferramenta B2B, ou algo que você está oferecendo para treinamento), esse número pode disparar. Apenas alguns meses atrás - em 2016 - eu lidei com uma empresa usando o IE8 em mais de 60% de suas máquinas.

Portanto, antes de fazer qualquer coisa: verifique qual navegador seus usuários usam . Se não o fizer, você aprenderá uma lição rápida e dolorosa sobre por que "funciona para mim" não é bom o suficiente em uma entrega para um cliente.

Minha resposta de 2008 segue.

No entanto, existem métodos não-viáveis ​​de uploads de arquivos. Você pode criar um iframe na página (que você esconde com CSS) e depois segmentar seu formulário para postar nesse iframe. A página principal não precisa se mover.

É um post "real", por isso não é totalmente interativo. Se você precisa de status, você precisa de algo do lado do servidor para processar isso. Isso varia enormemente dependendo do seu servidor. ASP.NET tem mecanismos mais agradáveis. O PHP plain falha, mas você pode usar as modificações Perl ou Apache para contornar isso.

Se você precisar de vários uploads de arquivos, é melhor fazer cada arquivo um de cada vez (para superar os limites máximos de upload de arquivos). Poste o primeiro formulário no iframe, monitore seu progresso usando o acima e, quando terminar, poste o segundo formulário no iframe e assim por diante.

Ou use uma solução Java / Flash. Eles são muito mais flexíveis no que podem fazer com seus posts ...


Eu tenho usado o script abaixo para fazer upload de imagens que funcionam bem.

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);
});

Explicação

Eu uso a resposta div para mostrar a animação e a resposta de upload após o upload ser concluído.

A melhor parte é que você pode enviar dados extras, como ids e etc, com o arquivo ao usar esse script. Eu mencionei extra-data como no script.

No nível do PHP, isso funcionará como upload normal de arquivos. extra-data pode ser recuperado como dados $_POST .

Aqui você não está usando um plugin e outras coisas. Você pode alterar o código como quiser. Você não está cegamente codificando aqui. Essa é a principal funcionalidade de qualquer upload de arquivo jQuery. Na verdade JavaScript.


Uma solução que encontrei foi fazer com que o <form> visasse um iFrame oculto. O iFrame pode então executar o JS para mostrar ao usuário que ele está completo (no carregamento da página).


Conclusão para futuros leitores.

Upload de arquivo assíncrono

Com HTML5

Você pode carregar arquivos com jQuery usando o método $.ajax() se FormData e a API File forem suportados (ambos os recursos HTML5).

Você também pode enviar arquivos sem FormData, mas de qualquer forma, a API File deve estar presente para processar arquivos de forma que eles possam ser enviados com 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 um exemplo rápido e puro de JavaScript ( sem jQuery ), consulte " Enviando arquivos usando um objeto FormData ".

Cair pra trás

Quando HTML5 não é suportado (nenhuma API de arquivo ), a única outra solução JavaScript pura (sem Flash ou qualquer outro plug-in de navegador) é a técnica de iframe oculto , que permite emular uma solicitação assíncrona sem usar o objeto XMLHttpRequest .

Consiste em definir um iframe como o destino do formulário com as entradas do arquivo. Quando o usuário envia uma solicitação é feita e os arquivos são enviados, mas a resposta é exibida dentro do iframe, em vez de renderizar novamente a página principal. Ocultar o iframe torna todo o processo transparente para o usuário e emula uma solicitação assíncrona.

Se feito corretamente, deve funcionar virtualmente em qualquer navegador, mas tem algumas ressalvas de como obter a resposta do iframe.

Neste caso, você pode preferir usar um plugin wrapper como o Bifröst que usa a técnica iframe, mas também fornece um transporte jQuery Ajax, permitindo enviar arquivos apenas com o método $.ajax() , da seguinte maneira:

$.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!");
});

Plugins

Bifröst é apenas um pequeno wrapper que adiciona suporte de fallback ao método ajax do jQuery, mas muitos dos plugins mencionados acima, como jQuery Form Plugin ou jQuery File Upload, incluem toda a pilha de HTML5 a diferentes fallbacks e alguns recursos úteis para facilitar o processo. Dependendo de suas necessidades e requisitos, talvez você queira considerar uma implementação simples ou um desses plug-ins.


Uma abordagem moderna sem o Jquery é usar o objeto FileList você retorna <input type="file">quando o usuário seleciona um arquivo (s) e, em seguida, use Fetch para postar o FileList contornado em torno de um 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
    })
});


Você pode usar

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

Demo


A maneira mais simples e mais robusta que fiz no passado é simplesmente segmentar uma tag iFrame oculta com o seu formulário - então ela será enviada dentro do iframe sem recarregar a página.

Isto é, se você não quiser usar um plugin, JavaScript ou qualquer outra forma de "mágica" que não seja HTML. Claro que você pode combinar isso com JavaScript ou o que você tem ...

<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>

Você também pode ler o conteúdo do iframe onLoad para erros do servidor ou respostas de sucesso e, em seguida, enviar a saída para o usuário.

Chrome, iFrames e onLoad

-note-você só precisa continuar lendo se você estiver interessado em como configurar um bloqueador de UI ao fazer o upload / download

Atualmente, o Chrome não aciona o evento onLoad para o iframe quando é usado para transferir arquivos. Firefox, IE e Edge todos disparam o evento onload para transferências de arquivos.

A única solução que encontrei funciona para o Chrome foi usar um cookie.

Para fazer isso basicamente quando o upload / download é iniciado:

  • [Lado do cliente] Inicie um intervalo para procurar a existência de um cookie
  • [Lado do servidor] Faça o que precisar com os dados do arquivo
  • [Lado do servidor] Definir cookie para o intervalo do lado do cliente
  • O [Client Side] Interval vê o cookie e o usa como o evento onLoad. Por exemplo, você pode iniciar um bloqueador de UI e, em seguida, onLoad (ou quando o cookie é feito) você remove o bloqueador de UI.

Usar um cookie para isso é feio, mas funciona.

Eu fiz um plugin jQuery para lidar com esse problema para o Chrome ao baixar, você pode encontrar aqui

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

O mesmo princípio básico se aplica ao upload também.

Para usar o downloader (inclua o 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');
 });

E no lado do servidor, pouco antes de transferir os dados do arquivo, crie o cookie

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

O plug-in verá o cookie e, em seguida, acionará o retorno de chamada onComplete .


Eu escrevi isso em um ambiente Rails . São apenas cerca de cinco linhas de JavaScript, se você usar o plugin leve do formulário jQuery.

O desafio é fazer com que o upload do AJAX funcione como o remote_form_for padrão que não entende o envio de formulários com várias partes. Ele não enviará os dados do arquivo que o Rails procura de volta com o pedido AJAX.

É aí que entra o plugin do formulário jQuery.

Aqui está o código Rails para isso:

<% remote_form_for(:image_form, 
                   :url => { :controller => "blogs", :action => :create_asset }, 
                   :html => { :method => :post, 
                              :id => 'uploadForm', :multipart => true }) 
                                                                        do |f| %>
 Upload a file: <%= f.file_field :uploaded_data %>
<% end %>

Aqui está o JavaScript associado:

$('#uploadForm input').change(function(){
 $(this).parent().ajaxSubmit({
  beforeSubmit: function(a,f,o) {
   o.dataType = 'json';
  },
  complete: function(XMLHttpRequest, textStatus) {
   // XMLHttpRequest.responseText will contain the URL of the uploaded image.
   // Put it in an image element you create, or do with it what you will.
   // For example, if you have an image elemtn with id "my_image", then
   //  $('#my_image').attr('src', XMLHttpRequest.responseText);
   // Will set that image tag to display the uploaded image.
  },
 });
});

E aqui está a ação do controlador Rails, bonita baunilha:

 @image = Image.new(params[:image_form])
 @image.save
 render :text => @image.public_filename

Eu tenho usado isso nas últimas semanas com o Bloggity, e funciona como um campeão.


Usando HTML5 e JavaScript , fazer o upload do async é bem fácil, eu crio a lógica de upload junto com o seu html, isso não está funcionando completamente pois precisa da API, mas demonstra como funciona, se você tem o endpoint chamado /uploadfrom root do seu site, este código deve funcionar para você:

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>

Além disso, algumas informações adicionais sobre XMLHttpReques:

O objeto XMLHttpRequest

Todos os navegadores modernos suportam o objeto XMLHttpRequest. O objeto XMLHttpRequest pode ser usado para trocar dados com um servidor da web nos bastidores. Isso significa que é possível atualizar partes de uma página da Web, sem recarregar a página inteira.


Crie um objeto XMLHttpRequest

Todos os navegadores modernos (Chrome, Firefox, IE7 +, Edge, Safari, Opera) têm um objeto XMLHttpRequest integrado.

Sintaxe para criar um objeto XMLHttpRequest:

variável = novo XMLHttpRequest ();


Acesso entre domínios

Por motivos de segurança, os navegadores modernos não permitem o acesso em vários domínios.

Isso significa que tanto a página da Web quanto o arquivo XML que ela tenta carregar devem estar localizados no mesmo servidor.

Os exemplos no W3Schools abrem todos os arquivos XML localizados no domínio W3Schools.

Se você quiser usar o exemplo acima em uma de suas próprias páginas da Web, os arquivos XML carregados devem estar localizados em seu próprio servidor.

Para mais detalhes, você pode continuar lendo here ...


Simples Ajax Uploader é outra opção:

https://github.com/LPology/Simple-Ajax-Uploader

  • Cross-browser - funciona no IE7 +, Firefox, Chrome, Safari, Opera
  • Suporta vários carregamentos simultâneos - mesmo em navegadores não HTML5
  • Sem flash ou CSS externo - apenas um arquivo Javascript de 5 KB
  • Suporte interno opcional para barras de progresso totalmente navegáveis ​​(usando a extensão APC do PHP)
  • Flexível e altamente personalizável - use qualquer elemento como botão de upload, estilize seus próprios indicadores de progresso
  • Não requer formulários, apenas forneça um elemento que servirá como botão de upload
  • Licença MIT - livre para usar em projetos comerciais

Exemplo de uso:

var uploader = new ss.SimpleUpload({
    button: $('#uploadBtn'), // upload button
    url: '/uploadhandler', // URL of server-side upload handler
    name: 'userfile', // parameter name of the uploaded file
    onSubmit: function() {
        this.setProgressBar( $('#progressBar') ); // designate elem as our progress bar
    },
    onComplete: function(file, response) {
        // do whatever after upload is finished
    }
});

Este plugin de upload de arquivo AJAX jQuery carrega o arquivo somehwere e passa a resposta para um retorno de chamada, nada mais.

  • Não depende de um HTML específico, apenas dê um <input type="file">
  • Não requer que o seu servidor responda de alguma forma particular
  • Não importa quantos arquivos você usa ou onde eles estão na página

- Use tão pouco quanto -

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

- ou tanto quanto -

$('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');
  }
});

Você pode passar parâmetros adicionais junto com o nome do arquivo ao fazer upload assíncrono usando XMLHttpRequest (sem dependência flash e iframe). Anexe o valor do parâmetro adicional com FormData e envie a solicitação de upload.

function uploadButtonCLicked(){
    var input = document.querySelector('input[type="file"]')

    fetch('/url', {
      method: 'POST',
      body: input.files[0]
    }).then(res => res.json())   // you can do something with response
      .catch(error => console.error('Error:', error))
      .then(response => console.log('Success:', response));
}                               

Além disso, o upload do arquivo Syncfusion JavaScript UI fornece solução para esse cenário simplesmente usando o argumento de evento. você pode encontrar documentação aqui e mais detalhes sobre este controle aqui digite a descrição do link aqui


Procure Manuseando o processo de upload de um arquivo de forma assíncrona aqui: https://developer.mozilla.org/pt-BR/docs/Using_files_from_web_applications

Amostra do link

<?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>

Você pode fazer o upload simplesmente com jQuery .ajax() .

HTML:

<form id="upload-form">
    <div>
        <label for="file">File:</label>
        <input type="file" id="file" name="file" />
        <progress class="progress" value="0" max="100"></progress>
    </div>
    <hr />
    <input type="submit" value="Submit" />
</form>

CSS

.progress { display: none; }

Javascript:

$(document).ready(function(ev) {
    $("#upload-form").on('submit', (function(ev) {
        ev.preventDefault();
        $.ajax({
            xhr: function() {
                var progress = $('.progress'),
                    xhr = $.ajaxSettings.xhr();

                progress.show();

                xhr.upload.onprogress = function(ev) {
                    if (ev.lengthComputable) {
                        var percentComplete = parseInt((ev.loaded / ev.total) * 100);
                        progress.val(percentComplete);
                        if (percentComplete === 100) {
                            progress.hide().val(0);
                        }
                    }
                };

                return xhr;
            },
            url: 'upload.php',
            type: 'POST',
            data: new FormData(this),
            contentType: false,
            cache: false,
            processData: false,
            success: function(data, status, xhr) {
                // ...
            },
            error: function(xhr, status, error) {
                // ...
            }
       });
    }));
});


Exemplo: Se você usar o jQuery, poderá fazer facilmente um arquivo de upload. Este é um pequeno e forte plugin jQuery, http://jquery.malsup.com/form/ .

Exemplo

var $bar   = $('.ProgressBar');
$('.Form').ajaxForm({
  dataType: 'json',

  beforeSend: function(xhr) {
    var percentVal = '0%';
    $bar.width(percentVal);
  },

  uploadProgress: function(event, position, total, percentComplete) {
    var percentVal = percentComplete + '%';
    $bar.width(percentVal)
  },

  success: function(response) {
    // Response
  }
});

Espero que seja útil


Você pode usar a API de busca mais recente por JavaScript. Como isso:

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

Vantagem: a API de busca é suportada nativamente por todos os navegadores modernos, portanto você não precisa importar nada. Além disso, observe que fetch () retorna um Promise que é então tratado de .then(..code to handle response..)forma assíncrona.


Você pode fazê-lo no JavaScript de baunilha com bastante facilidade. Aqui está um trecho do meu projeto atual:

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);

Nota: Esta resposta está desatualizada, agora é possível fazer upload de arquivos usando o XHR.

Você não pode carregar arquivos usando XMLHttpRequest (Ajax). Você pode simular o efeito usando um iframe ou Flash. O excelente jQuery Form Plugin que publica seus arquivos através de um iframe para obter o efeito.


Eu recomendo usar o plugin Fine Uploader para esse propósito. Seu código JavaScript seria:

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




upload