2013-07-17 11 views
6

Attualmente sto aggiornando parti di un sito Web ASP.NET MVC per essere più RESTful, utilizzando l'API Web ASP.NET. Una delle funzionalità che stiamo passando a un progetto più RESTful è il caricamento di file. Per il client, stiamo utilizzando un plug-in jquery, ajaxForm, per completare la creazione di un iframe che invierà il modulo contenente l'elemento di input del file. Funzionava perfettamente con ASP.NET MVC.IE iframe non gestisce correttamente l'applicazione/la risposta JSON

Quando lo si modifica per utilizzare il nostro endpoint API Web, che restituisce una risposta con un Content-Type di "application/json", abbiamo rilevato problemi con Internet Explorer 9. Sembra che la funzione di successo ajaxForm non sia mai stata chiamata. Da quello che posso dire, sembra che l'iframe in IE interpreti il ​​corpo di una risposta con un Content-Type di "application/json" come un file allegato da scaricare. Ciò significa che non genera mai l'evento "caricato" dell'iframe, il che significa che il gestore di eventi onload ajaxForm non verrà mai attivato e la nostra funzione di successo ajaxForm non verrà mai chiamata.

Abbiamo notato il problema anche in IE 7, ma non è stato possibile ricreare il problema nelle ultime versioni di Firefox o Chrome, anche quando li abbiamo costretti a utilizzare un iframe anziché File API con FormData.

Per risolvere questo problema per ora, ora sto forzando la risposta Content-Type a "text/plain", che è ciò che stavamo restituendo in precedenza dalle azioni del controller MVC ASP.NET che gestiva il caricamento di file. Questo fa sì che tutto funzioni di nuovo.

Le mie domande:

  • C'è un modo per mantenere il Web API risposta Content-Type come "application/json" e ho IE interpretarlo correttamente?
  • C'è un modo migliore di caricare file quando si utilizzano IE e Web API? Forse un plugin diverso o una tecnica migliore?

Restrizioni aggiuntive: non è possibile utilizzare ActiveX o Flash per questo sito Web. Posso usare un plugin diverso, ma solo se ha un supporto generale per browser. (IE, Chrome, Firefox, Safari, ecc)

mio HTML:

<form id="uploadFormId" action="" method="post" enctype="multipart/form-data" encoding="multipart/form-data"> 
    <input type="file" name="files[]"/> 
</form> 

mio javascript:

function onFileChange(e) { 
    if (e.type === e.originalEvent.type) { 
     var filePath = $(e.currentTarget).val(); 
     if (filePath !== '') { 
      $(this).closest('form').submit(); 
     } 
    } 
}; 

$(function() { 
    $('#uploadFormId').ajaxForm({ 
     url: "api/Files/1234", 
     dataType: 'json', 
     success: function (response) { 
      alert(response); 
     }, 
     error: function (xhr, status, error) { 
      alert(status); 
     } 
    }); 
    $('#uploadFormId input[type="file"]').bind('change', onFileChange); 
}); 

"/ JSON applicazione" headers di risposta (non funziona in IE) :

Cache-Control:no-cache 
Content-Length:337 
Content-Type:application/json; charset=utf-8 
Date:Wed, 17 Jul 2013 13:10:47 GMT 
Expires:-1 
Pragma:no-cache 
Server:Microsoft-IIS/8.0 
X-AspNet-Version:4.0.30319 
X-Powered-By:ASP.NET 

"text/plain" header di risposta (opere in IE):

Cache-Control:no-cache 
Content-Length:322 
Content-Type:text/plain 
Date:Wed, 17 Jul 2013 13:17:24 GMT 
Expires:-1 
Pragma:no-cache 
Server:Microsoft-IIS/8.0 
X-AspNet-Version:4.0.30319 
X-Powered-By:ASP.NET 

risposta

9

Quando ajaxForm utilizza la modalità di invio iframe, la risposta della chiamata viene necessariamente visualizzata nel corpo dell'iframe. Ciò significa che deve essere un tipo di contenuto che il browser può eseguire il rendering, in genere HTML, ma anche text/plain funzionerà. Tuttavia, il browser non può eseguire il rendering di application/json come pagina.

C'è anche un problema specifico con l'uso di text/plain, in quanto i browser possono accontentarlo, e trattare la risorsa come HTML se c'è qualcosa che assomiglia a un tag HTML nei dati. Se il tuo JSON torna con i dati forniti dall'utente in esso, ciò potrebbe consentire a qualcuno di iniettare JavaScript eseguibile nel tuo sito (attacco XSS).

come suggerito dal ajaxForm doc ci si aspetta di rilevare quando la chiamata proviene da un posto iframe invece di AJAX, e restituire una risposta text/html con un wrapper textarea in quel caso:

Per spiegare la sfide dello script e delle risposte JSON quando si utilizza la modalità iframe, il plug-in modulo consente di incorporare queste risposte in un elemento textarea e si consiglia di farlo per questi tipi di risposta quando viene utilizzato in combinazione con caricamenti di file e browser precedenti.

+0

Alla domanda "Perché IE9 + si comporta in questo modo": il trattamento di un'applicazione/json come un tipo di file corretto (che porta a un download di file piuttosto che sniffare in un altro formato) era una correzione di sicurezza per IE9. – EricLaw

Problemi correlati