Ho creato un controller WebAPI, basato su MVC 5, che fornisce file diversi per i nostri clienti. Lo strumento per accedere ai file è anche auto-scritto - basato su .NET HttpClient - ma questa è un'altra storia.MVC 5 WebAPI - Download file - HttpException
Nella prima versione del controller scaricare ho usato la configurazione in meccanismo per fornire i file come this
Ma questo meccanismo si è schiantato sul mio IIS per i file> 4GB.
Così ho finalmente venuto a questo codice:
public class DownloadController : ApiController
{
public async Task Get(long id)
{
string fullFilePath = GetFilePathById(id);
string returnFileName = fullFilePath.Split('\\').Last();
FileInfo path = new FileInfo(fullFilePath);
HttpContext.Current.Response.ContentType = "application/zip";
HttpContext.Current.Response.AddHeader("Content-Length", path.Length.ToString());
HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment; filename=" + returnFileName);
HttpContext.Current.Response.Flush();
try
{
byte[] buffer = new byte[4096];
using (FileStream fs = path.OpenRead())
{
using (BufferedStream bs = new BufferedStream(fs, 524288))
{
int count = 0;
while ((count = bs.Read(buffer, 0, buffer.Length)) > 0)
{
if (!HttpContext.Current.Response.IsClientConnected)
{
break;
}
HttpContext.Current.Response.OutputStream.Write(buffer, 0, count);
HttpContext.Current.Response.Flush();
}
}
}
}
catch (Exception exception)
{
//Exception logging here
}
}
}
Questo codice funziona molto bene e ho avuto download veloci con l'utilizzo della CPU accettabili e del disco I/O. Ma dopo qualche tempo ho notato che - con ogni singolo file - un'eccezione non gestita scrive una voce nell'applicazione Eventlog del server IIS in questo modo:
Server cannot set status after HTTP headers have been sent
Exception type: HttpException
Event Log ID 1309
Sono sicuro che l'uso ricorrente di .Flush() causa il problema, ma se rimuovo qualcuno di questi il download smette di funzionare.
In domande simili posso trovare Response.BufferOutput = true;
come soluzione ma sembra che mangi tutte le risorse del mio server e ritardi il download.
Qualsiasi suggerimento sarebbe fantastico!
Hai provato ad aggiungere un 'HttpContext.Current.Response.Close()' alla fine? Oppure, se applicabile (e non hai bisogno di ulteriori elaborazioni), 'HttpContext.Current.ApplicationInstance.CompleteRequest()'? – Jcl
Qual è il motivo per cui non si utilizza StreamContent? – martennis
@Jcl Ci proverò e ti darò un feedback. – maltmann