简体   繁体   中英

WCF Download File Aborted By Client

I have the following code for downloading large files. It reads from a filestream and writes to the Response.Outputstream.

It seems to be working, ie, the file appears to dowload (actually it seems to be downloading more, weirdly) but it fails at the end. Chrome gives a "Network error" and IE shows "(Aborted)"

    [OperationContract]
    [WebInvoke(UriTemplate = "/f/{key}", Method = "GET")]
    public void LargeFileDownload(string key)
    {
        var identifier = PublicIdentifier.FromString(key, true);
        if (identifier.Type == PublicIdentifier.IdentifierType.DocumentDownload)
        {
            Document doc = Business.Documents.GetById(Application.SystemUser, identifier.Id);

            string tempName = Path.GetTempPath() + doc.OriginalFileName;

            int bufferSize = 8192;
            FileStream fstream = new FileStream(tempName, FileMode.Open, FileAccess.Read);
            long fileSize = fstream.Length;

            HttpContext.Current.Response.Clear();
            HttpContext.Current.Response.ClearHeaders();
            HttpContext.Current.Response.ClearContent();
            HttpContext.Current.Response.ContentType = doc.ContentType;

            string contentDisposition = string.Format("{0};filename={1}{2}", "attachment", doc.Name.Replace(" ", "_"), Path.GetExtension(doc.OriginalFileName));
            HttpContext.Current.Response.AddHeader("Content-Disposition", contentDisposition);
            HttpContext.Current.Response.AddHeader("Content-Length", fileSize.ToString());

            WebOperationContext.Current.OutgoingResponse.ContentType = doc.ContentType;
            try
            {
                byte[] buffer = new byte[bufferSize];

                int bytesRead = 0;
                while ((bytesRead = fstream.Read(buffer, 0, bufferSize)) > 0)
                {
                    HttpContext.Current.Response.OutputStream.Write(buffer, 0, bufferSize);
                    HttpContext.Current.Response.Flush();
                }
            }
            finally
            {
                if (fstream != null)
                    fstream.Close();

                //File.Delete(tempName);
            }
        }
    }

Updated code:-

    [OperationContract]
    [WebInvoke(UriTemplate = "/f/{key}", Method = "GET")]
    public void LargeFileDownload(string key)
    {
        var identifier = PublicIdentifier.FromString(key, true);
        if (identifier.Type == PublicIdentifier.IdentifierType.DocumentDownload)
        {
            Document doc = Business.Documents.GetById(Application.SystemUser, identifier.Id);

            string tempName = Path.GetTempPath() + doc.OriginalFileName;

            int bufferSize = 8192;
            FileStream fstream = new FileStream(tempName, FileMode.Open, FileAccess.Read);
            long fileSize = fstream.Length;

            HttpContext.Current.Response.Clear();
            HttpContext.Current.Response.ClearHeaders();
            HttpContext.Current.Response.ClearContent();
            HttpContext.Current.Response.ContentType = "application/octet-stream";

            string contentDisposition = string.Format("{0};filename={1}{2}", "attachment", doc.Name.Replace(" ", "_"), Path.GetExtension(doc.OriginalFileName));
            HttpContext.Current.Response.AddHeader("Content-Disposition", contentDisposition);
            HttpContext.Current.Response.AddHeader("Content-Length", fileSize.ToString());

            HttpContext.Current.Response.ContentType = "application/octet-stream";
            try
            {
                byte[] buffer = new byte[bufferSize];

                int bytesRead = 0;
                while ((bytesRead = fstream.Read(buffer, 0, bufferSize)) > 0)
                {
                    HttpContext.Current.Response.OutputStream.Write(buffer, 0, bytesRead);
                    HttpContext.Current.Response.Flush();
                }
            }
            finally
            {
                if (fstream != null)
                    fstream.Close();

                //File.Delete(tempName);
            }
        }
    }

Fiddler raw:-

HTTP/1.1 504 Fiddler - Receive Failure
Date: Wed, 17 Oct 2018 11:53:09 GMT
Content-Type: text/html; charset=UTF-8
Connection: close
Cache-Control: no-cache, must-revalidate
Timestamp: 12:53:09.099

[Fiddler] ReadResponse() failed: The server did not return a complete response for this request. Server returned 13,912,938 bytes.

You're setting Content-Length correctly and the browser assumes that value is true. But because of this bug you're sending more data (which is garbage):

HttpContext.Current.Response.OutputStream.Write(buffer, 0, bufferSize);

This should not be bufferSize but bytesRead . This leads to a protocol error causing the browser to abort its processing.

The copy loop should probably be replaced by a call to TransmitFile , or at least by Stream.Copy .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM