WCF Скачать файл прерван клиентом - PullRequest
0 голосов
/ 14 октября 2018

У меня есть следующий код для загрузки больших файлов.Он читает из файлового потока и записывает в Response.Outputstream.

Кажется, он работает, т. Е. Файл, кажется, загружается (на самом деле он загружает больше, странно), но в конце он терпит неудачу.Chrome выдает «Ошибка сети», а IE показывает «(Прервано)»

    [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);
            }
        }
    }

Обновленный код: -

    [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.

1 Ответ

0 голосов
/ 14 октября 2018

Вы устанавливаете Content-Length правильно, и браузер предполагает, что значение равно true.Но из-за этой ошибки вы отправляете больше данных (что является мусором):

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

Это должно быть не bufferSize, а bytesRead.Это приводит к ошибке протокола, из-за которой браузер прерывает свою обработку.

Цикл копирования, вероятно, следует заменить вызовом TransmitFile или, по крайней мере, Stream.Copy.

...