Sorun, WebApi 2 ve bir Async ApiController - tabanlı Get yöntemini kullanırken, bir dosyanın içeriğini döndürmesidir. Get yöntemini eşzamanlı olarak değiştirdiğimde, yalnızca gayet iyi çalışır, ancak onu tekrar uyumsuz duruma döndürdüğümde akışı derhal kapatır. -----C# Async ApiController OutputStream Kapanışı Erken Başlangıçta
public async Task GetDownloadStream(string fileIdentifier, Stream streamToCopyTo)
{
string filePath = Path.Combine(fileIdentifierFolder, fileIdentifier);
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.None, BufferSize, false))
{
fs.CopyTo(streamToCopyTo);
}
}
-------- zaman uyumsuz kod:
public void Get(int id)
{
try
{
FileInfo fileInfo = logic.GetFileInfoSync(id);
HttpResponse response = HttpContext.Current.Response;
response.Clear();
response.ClearContent();
response.Buffer = true;
response.AddHeader("Content-Disposition", "attachment; filename=\"" + fileInfo.Node.Name + fileInfo.Ext + "\"");
response.AddHeader("Content-Length", fileInfo.SizeInBytes.ToString());
response.ContentType = "application/octet-stream";
logic.GetDownloadStreamSync(id, response.OutputStream);
response.StatusCode = (int)HttpStatusCode.OK;
//HttpContext.Current.ApplicationInstance.CompleteRequest();
response.End();
}
catch(Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
Ve şöyle GetDownloadStreamSync bağlıdır: (Fiddler bağlantısı iptal edildi bildiriyor) çalışma Senkron koddur -----
zaman uyumsuz sürümü hariç tamamen aynı olduğu: GetDo eşzamansız uygulamasıyla
public async Task Get(int id)
{
FileInfo fileInfo = await logic.GetFileInfoSync(id); // database opp
HttpResponse response = HttpContext.Current.Response;
response.Clear();
response.ClearContent();
response.Buffer = true;
response.AddHeader("Content-Disposition", "attachment; filename=\"" + fileInfo.Node.Name + fileInfo.Ext + "\"");
response.AddHeader("Content-Length", fileInfo.SizeInBytes.ToString());
response.ContentType = "application/octet-stream";
await logic.GetDownloadStreamSync(id, response.OutputStream);
//database opp + file I/O
response.StatusCode = (int)HttpStatusCode.OK;
//HttpContext.Current.ApplicationInstance.CompleteRequest();
response.End();
}
wnloadStream şöyle: yani umarım birileri bu neden başarısız olacağını farkındadır Biz önden arkaya doğru zaman uyumsuz/bekliyoruz desen kucaklamaya çalışıyoruz
public async Task GetDownloadStream(string fileIdentifier, Stream streamToCopyTo)
{
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.None, BufferSize, true))
{
await fs.CopyToAsync(streamToCopyTo);
}
}
(streamToCopyTo response.OutputStream gelen OutputStream olan)? Ayrıca Response.End(), Response.Flush() ve HttpContext.Current.ApplicationInstance.CompleteRequest() çağırmayı denedim. Ayrıca, aşağıdaki sorulara/yorumlara yanıt olarak, GetDownloadStream yöntemine isabet edilmemesi sonucu response.End() üzerinde bir kesme noktası koymuştum. Belki de OutputStream asenkron değil mi? Herhangi bir fikir açığız! Teşekkürler
************************** Son Çözüm **************** ***********
Yorum yapan herkese ve özellikle de FileOptions.DeleteOnClose hakkındaki önerisi için @Noseratio'ya büyük teşekkürler. GetDownloadStreamAsync böyle bakarken
[HttpGet]
public async Task<HttpResponseMessage> Get(long id)
{
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
Node node = await logic.GetFileInfoForNodeAsync(id);
result.Content = new StreamContent(await logic.GetDownloadStreamAsync(id));
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = node.Name + node.FileInfo.Extension
};
result.Content.Headers.ContentLength = node.FileInfo.SizeInBytes;
return result
}
:
FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.None, BufferSize, FileOptions.DeleteOnClose | FileOptions.Asynchronous);
ben de anında dosya akışı şifresini edildi ve bu, çalışır dışarı bıraktı
ilgilenenler ...
için çokFileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.None, BufferSize, FileOptions.DeleteOnClose | FileOptions.Asynchronous);
RijndaelManaged rm = new RijndaelManaged();
return new CryptoStream(fs, GetDecryptor(rm, password), CryptoStreamMode.Read);
MSDN'ın açıklama budur. "Bir o üzerinde çalıştığı konu engellemez ifadesini bekliyor Bunun yerine, neden derleyici async metodunun geri kalanını, beklenen bir görev olarak devam ettirmek için kaydolur.Daha sonra async metodunun arayıcısına geri döner.Göre tamamlandığında, devam eder ve async metodunun icrası kaldığı yerden devam eder. Bekleyen bir ifade, yalnızca bir derleyici, lambda ifadesi veya bir anync değiştirici tarafından işaretlenen anonim bir yöntemde ortaya çıkabilir. Başka bir yerde, bir tanımlayıcı olarak yorumlanır. " – user1789573
Yöntem async imzası nedir dava? (Task Get ... 'i farz ediyorum, ama emin olun). Eğer söz konusu bir şey kaçırmak durumunda –
, tam zaman uyumsuz sürümü gönderebilir miyim? – EZI