Загрузка файла кусками в ответе http-context C #

У меня есть сценарий ниже.

Клиент отправляет запрос на Сервер-1 для загрузки файла. Сервер-1 отправляет запрос на Сервер-2 для загрузки файла.

Чтобы выполнить эту работу, мне нужно создать механизм, в котором после того, как клиент отправит запрос на Сервер-1, Сервер-1 будет запрашивать на Сервер-2, который будет отправлять файл в виде потока вывода ответа по частям. Сервер-1 будет постоянно отправлять фрагменты этого файла в браузер клиента, поскольку он продолжает получать от сервера-2.

Я написал код, как показано ниже, теоретически он выглядит нормально, но все же не работает. Он не загружает весь файл в клиентском браузере, похоже, что последний фрагмент не передается на Сервер-1 или он не загружается в клиентский браузер с Сервера-1.

Код сервера-1 (где клиент запрашивает загрузку файла)

    private void ProccesBufferedResponse(HttpWebRequest webRequest, HttpContext context)
    {
        char[] responseChars = null;
        byte[] buffer = null;

        if (webRequest == null)
            logger.Error("Request string is null for Perfios Docs Download at ProccesBufferedResponse()");

        context.Response.Buffer = false;
        context.Response.BufferOutput = false;
        try
        {

            WebResponse webResponse = webRequest.GetResponse();
            context.Response.ContentType = "application/pdf";
            context.Response.AddHeader("Content-disposition", webResponse.Headers["Content-disposition"]);

            StreamReader responseStream = new StreamReader(webResponse.GetResponseStream());
            while (!responseStream.EndOfStream)
            {
                responseChars = new char[responseStream.ToString().ToCharArray().Length];
                responseStream.Read(responseChars, 0, responseChars.Length);
                buffer = Encoding.ASCII.GetBytes(responseChars);

                context.Response.Clear();
                context.Response.OutputStream.Write(buffer, 0, buffer.Length);
                context.Response.Flush();

            }

        }
        catch (Exception ex)
        {
            throw;
        }
        finally
        {
            context.Response.Flush();
            context.Response.End();
        }
    }

Код Сервера-2 (где Сервер-1 отправит запрос на файл)

    private void DownloadInstaPerfiosDoc(int CompanyID, string fileName, string Foldertype)
    {
        string folderPath;
        string FilePath;
        int chunkSize = 1024;
        int startIndex = 0;
        int endIndex = 0;
        int length = 0;
        byte[] bytes = null;
        DirectoryInfo dir;

        folderPath = GetDocumentDirectory(CompanyID, Foldertype);
        FilePath = folderPath + "\\" + fileName;
        dir = new DirectoryInfo(folderPath);
        HttpContext.Current.Response.Buffer = false;
        HttpContext.Current.Response.BufferOutput = false;

        if (dir.Exists && dir.GetFiles().Length > 0)
        {
            foreach (var file in dir.GetFiles(fileName))
            {
                FilePath = folderPath + "\\" + file.Name;
                FileStream fsReader = new FileStream(FilePath, FileMode.Open, FileAccess.Read);

                HttpContext.Current.Response.ContentType = "application/pdf";
                HttpContext.Current.Response.AddHeader("Content-disposition", string.Format("attachment; filename = \"{0}\"", fileName));

                int totalChunks = (int)Math.Ceiling((double)fsReader.Length / chunkSize);
                for (int i = 0; i < totalChunks; i++)
                {
                    startIndex = i * chunkSize;

                    if (startIndex + chunkSize > fsReader.Length)
                        endIndex = (int)fsReader.Length;
                    else
                        endIndex = startIndex + chunkSize;

                    length = (int)endIndex - startIndex;
                    bytes = new byte[length];
                    fsReader.Read(bytes, 0, bytes.Length);
                    HttpContext.Current.Response.Clear();
                    HttpContext.Current.Response.OutputStream.Write(bytes, 0, bytes.Length);
                    HttpContext.Current.Response.Flush();
                }
            }
        }
    }

Пожалуйста, помогите мне решить эту проблему.


person Krunal Zala    schedule 16.11.2018    source источник
comment
Можете поделиться кодом, который вы пробовали?   -  person Matt Evans    schedule 16.11.2018
comment
Ключевое слово, которое вы ищете, разделено на части.   -  person Jimbot    schedule 16.11.2018
comment
Возможно ли, что если я отправлю ответ по частям, он будет загружен в клиентский браузер? @Jimbot   -  person Krunal Zala    schedule 16.11.2018
comment
Да, он в http 1.1, так что почти все браузеры совместимы   -  person Jimbot    schedule 16.11.2018


Ответы (1)


Это возможно и осуществимо. Я дам вам псевдо-процедуру, чтобы вы поняли общую идею.

Сервер1

download action gets hit
create a request to server2
get the response stream of your server2 request
read the response stream in desired chunk sizes until it's consumed completely
write each chunk (as soon as you read) to current response stream

Сервер2

download action gets hit
write your stream onto your current response stream however you like
person Tolga Evcimen    schedule 16.11.2018
comment
Да, я понимаю концепцию. Но что произойдет, если мне нужно завершить текущий ответ на сервере 1, потому что, пока я не завершу ответ, он не будет загружен в браузер клиента. - person Krunal Zala; 16.11.2018
comment
Спасибо, что подтвердили, что это возможно :) - person Krunal Zala; 16.11.2018