2012-05-17 14 views
28

Sfondo del problema.MVC3 HttpPostedFileBase Il primo caricamento non fornisce dati, ma Successivo

EDIT 3 posso verificare che questo sembra essere di nuovo a lavorare in Chrome 20. Grazie!

TLDR Aggiornamento

EDIT 2 Dopo ulteriormente pasticciare in giro questo sembra essere un bug in Chrome 19. Si prega di consultare qui:

http://groups.google.com/a/chromium.org/group/chromium-bugs/browse_thread/thread/15bc4992bcd4be1d/b905e8de20ee58fa?lnk=raot

Niente come un fino a il piccolo bug! :-)

Firefox-latest e IE8/9 funzionano come previsto. I registri di Fiddler mostrano lo stesso comportamento con la differenza principale che il secondo controllo di autorizzazione 401 non invia il payload del modulo confuso e funziona come previsto.

Sembra un caso di test e una soluzione è in lavorazione! Quindi, speriamo che qualcuno di voi là fuori che potrebbe essersi imbattuto in questo, aiuta!

FINE TLDR

Ho un azione di controllo che prende in solo un file caricato, che è un file CSV di "eventi". Dietro le quinte, questo CSV viene analizzato, trasformato in oggetti Event e i dati vengono sincronizzati nel database. Come risultato, all'utente viene richiesto di scaricare un foglio di lavoro Excel contenente tutti gli errori su ciascuna riga verificatasi.

Questo tutto funziona bene localmente sulla mia macchina di sviluppo. Una volta implementato nell'ambiente DEV, ottengo risultati diversi. Il primo tentativo di caricare un file risulta nello stato del flusso, qual è la parola che sto cercando qui, illeggibile? Segnala correttamente la sua lunghezza ma i tentativi di estrarre l'informazione non ottengono nulla. Letture successive hanno i dati e tutto funziona come previsto.

Ti darò i codici pertinenti. In primo luogo, il modulo HTML gen'd semplificata:

<form action="/Events/ImportLocal" enctype="multipart/form-data" method="post"> 

<input id="uploadFile" name="uploadFile" type="file" /> 
<input type="submit" value="Upload Events" />  

</form> 

piuttosto semplice:

azione Controller (perdonate la confusione, ho stato hacking a questo per un paio d'ore la società):

[HttpPost] 
public ActionResult ImportLocal(HttpPostedFileBase uploadFile) 
{ 
    if (uploadFile == null || uploadFile.ContentLength <= 0) 
    { 
     BaseLogger.Info("uploadFile is null or content length is zero..."); 
     //Error content returned to user 
    } 

    BaseLogger.InfoFormat("Community Import File Information: Content Length: {0}, Content Type: {1}, File Name: {2}", 
    uploadFile.ContentLength, uploadFile.ContentType, uploadFile.FileName); 

//This logger line is always reporting as correct. Even on the attempts where I can't pull out the stream data, I'm seeing valid values here. 
//EXAMPLE output on failed attempts: 
//Import File Information: Content Length: 315293, Content Type: application/vnd.ms-excel, File Name: Export_4-30-2012.csv 

    BaseLogger.InfoFormat("Upload File Input Stream Length: {0}", uploadFile.InputStream.Length);   
//This is reporting the correct length on failed attempts as well 


//I know the below is overly complicated and convoluted but I'm at a loss for why the inputstream in HttpPostedFileBase is not pulling out as expected 
//so I've been testing 
     var target = new MemoryStream(); 
     uploadFile.InputStream.CopyTo(target); 
     byte[] data = target.ToArray(); 
     BaseLogger.InfoFormat("File stream resulting length = {0}", data.Length); 
//This reports correctly. So far so good. 

     StringReader stringOut; 
     var stream = new MemoryStream(data) {Position = 0}; 

     using (var reader = new StreamReader(stream)) 
     { 
      string output = reader.ReadToEnd(); 
      BaseLogger.InfoFormat("Byte[] converted to string = {0}", output); 
//No go...output is reported to be empty at this point so no data ever gets sent on to the service call below 
      stringOut = new StringReader(output); 
     } 


     //Build up a collection of CommunityEvent objects from the CSV file 
     ImportActionResult<Event> importActionResults = _eventImportServices.Import(stringOut); 

L'obiettivo è passare un textreader o un stringreader al metodo di servizio, poiché dietro le quinte si sta utilizzando un'implementazione di elaborazione CSV che desidera questi tipi.

Qualche idea per quale motivo la prima richiesta non riesce ma i lavori successivi? Sento che ho bisogno di un nuovo paio di occhi mentre mi sto esaurendo le idee.

Ultimo punto, IIS 7.5 è la destinazione sia localmente tramite IIS Express che sul server di destinazione.

Grazie

EDIT per la generosità:

che sto copiando il mio messaggio di taglie qui e l'uscita Fiddler per ogni richiesta

Ho aggiunto alcuni commenti a questa domanda. Il problema sembra correlato a NTLM. Quello che vedo in Fiddler è un 401 Non autorizzato su richiesta 1 con dati di modulo validi (punto, è a mia conoscenza che queste prime due 401 richieste non autorizzate sono "normali" in scenari in cui è attiva solo l'autenticazione di Windows, verificare per favore?). La richiesta 2 elencata è ancora una 401 con gli stessi dati del modulo eccetto il file caricato. I dati ora sono solo un mucchio di scatole, le stesse dimensioni dei dati, ma non i dati esatti caricati. Richiesta 3 è un OK 200 che contiene i dati confusi e questo è ciò che sta ottenendo l'azione del mio controller. Come posso far sì che NTLM funzioni correttamente con gli upload di file?

ecco l'output Fiddler per ogni richiesta:

Richiesta 1) enter image description here

Richiesta 2) enter image description here

E infine richiesta 3 che è il HTTP elaborato 200 OK enter image description here

EDIT 2 Dopo ulteriormente pasticciare su questo sembra essere un bug in Chrome 19. Si prega di vedere qui:

http://groups.google.com/a/chromium.org/group/chromium-bugs/browse_thread/thread/15bc4992bcd4be1d/b905e8de20ee58fa?lnk=raot

Niente come un up al bug minuto! :-)

Firefox-latest e IE8/9 funzionano come previsto. I registri di Fiddler mostrano lo stesso comportamento con la differenza principale che il secondo controllo di autorizzazione 401 non invia il payload del modulo confuso e funziona come previsto.

Sembra un caso di test e una soluzione è in lavorazione! Quindi, speriamo che qualcuno di voi là fuori che potrebbe essersi imbattuto in questo, aiuta!

Grazie

+0

Come followup tutti, questo sembra essere correlato all'utilizzo di autenticazione rigorosamente di Windows. Autenticazione di Windows è attiva e Anonimo è disattivato sul sito. Dopo aver acceso Fiddler, vedo che lo standard 2 ha fallito 401 richieste di autorizzazione con NTLM. Questo è dove si verifica il problema. Alla prima richiesta di autorizzazione 401 fallita, vedo il modulo inviato con i dati di caricamento file corretti. Sulla seconda richiesta di autorizzazione 401 fallita, tuttavia, i dati del modulo sono confusi. È la dimensione corretta ma non i dati corretti. Ottengo 309 KB (o qualunque sia la dimensione) o NUL caratteri durante la visualizzazione dell'output nel blocco note ++ – Khepri

+0

Continua: abbiamo diversi livelli di autorizzazione nell'app che si basano sull'identità dell'utente, quindi la modifica dell'applicazione da eseguire con un account di servizio che otterrebbe neanche io da parte mia non è un'opzione, almeno non ci credo. C'è un modo per non dover attivare la rappresentazione e utilizzare un account di servizio per consentire un caricamento di successo? – Khepri

+1

+1 per una domanda significativamente ben documentata e per mantenere tutto aggiornato. –

risposta

1

questo è solo un idea per provare. Si noti che StreamReader ha molti costruttori:

http://msdn.microsoft.com/en-us/library/system.io.streamreader.aspx

In alcuni costruttori si tenta di rilevare automaticamente la codifica (se specificato) e se non è possibile rilevare poi si ripiega a quella specificata. Il costruttore utilizzato utilizza la codifica UTF-8. È possibile modificare il costruttore per rilevare automaticamente la codifica e, in caso contrario, utilizzare UTF-8.

1

Penso che sia necessario verificare le autorizzazioni sulla cartella IIS/sito Web virtuale in cui i file vengono caricati e dir se stessi se si trovano in luoghi distinti.

1

Buona domanda. L'autenticazione è stata la prima cosa che mi è venuta in mente. È normale ottenerne due non autorizzati e il terzo autorizzato. Questo è proprio il modo in cui funziona NTLM.

Se si ha la necessità di farlo funzionare anche su Chrome e non si può attendere la correzione suggerirei di abilitare l'autenticazione Forms che reindirizza allo stesso dominio ma su una porta diversa, dove risiede l'applicazione LOGIN con l'autenticazione di Windows. Questa app imposta o meno il cookie del modulo e ti rimanda all'app principale. Il processo è ben descritto qui: http://msdn.microsoft.com/en-us/library/ms972958.aspx

In questo modo, NTLM viene eseguito una volta e quindi si dispone di un cookie, quindi NTLM non viene utilizzato con la richiesta POST e tutto dovrebbe funzionare come previsto.

Ho appena pensato di condividere questo :)

Problemi correlati