Есть ли способ обрабатывать чанки в чанковом запросе после их получения?

Надеюсь, я правильно объясню. У меня есть веб-служба С# с почтовым методом get_file(), со стороны моего клиента я делаю POST-запрос к этому методу на своем сервере с фрагментацией кодирования передачи и отправляю файл фрагментами.

Метод запускается после выполнения запроса (вводится 0\r\n\r\n), есть ли способ обработать каждый фрагмент, как только я получу его на сервер, вместо того, чтобы ждать до конца?

Может быть, альтернатива отправки нескольких запросов POST была бы лучше? (но затем я получаю сообщение об ошибке после ~ 100 запросов).

Опять же, я надеюсь, что это объяснил правильно. заранее спасибо


person DanielY    schedule 21.10.2015    source источник
comment
Если вы просто хотите иметь возможность читать данные по мере их поступления (но не видеть отдельные фрагменты), тогда tech.edelste.in/post/116646600708/ должен помочь.   -  person Richard    schedule 21.10.2015
comment
Я хотел бы иметь возможность обработать кусок (сделать что-то с ним) немедленно   -  person DanielY    schedule 22.10.2015


Ответы (1)


Насколько я понимаю, вы хотите, чтобы клиент С# загружал большой файл кусками на сервер, на котором размещена ваша служба С#.

В этом случае я уже некоторое время использовал следующее решение, и оно показало себя очень надежным:

Функция на стороне сервера:

    [WebMethod]
    public void UploadFile(string FileName, byte[] buffer, long Offset, out bool UploadOK, out string msg)
    {
        Log(string.Format("Upload File {0}. Offset {1}, Bytes {2}...", FileName, Offset, buffer.Length));
        UploadOK = false;
        try
        {
            // setting the file location to be saved in the server. 
            // reading from the web.config file 
            string FilePath = Path.Combine( ConfigurationManager.AppSettings["upload_path"], FileName);

            if (Offset == 0) // new file, create an empty file
                File.Create(FilePath).Close();
            // open a file stream and write the buffer. 
            // Don't open with FileMode.Append because the transfer may wish to 
            // start a different point
            using (FileStream fs = new FileStream(FilePath, FileMode.Open,
                FileAccess.ReadWrite, FileShare.Read))
            {
                fs.Seek(Offset, SeekOrigin.Begin);
                fs.Write(buffer, 0, buffer.Length);
            }
            UploadOK = true;
            msg = "uploaded to " + FilePath;

            Log(string.Format("Sucessfully Uploaded to File {0}: {1}", FileName, msg));
        }
        catch (Exception ex)
        {
            //sending error:
            msg = "failed to upload: " + ex.Message;
            UploadOK = false;
            Log(string.Format("Failed Upload File {0}: {1}", EmlFileName, ex.Message));
        }
    }

Функция загрузки на стороне клиента:

static void SendFile(YourWebService webservice, string filename)
    {
        Console.WriteLine("uploading file: " + filename);

        int Offset = 0; // starting offset.

        //define the chunk size
        int ChunkSize = 65536; // 64 * 1024 kb

        //define the buffer array according to the chunksize.
        byte[] Buffer = new byte[ChunkSize];
        //opening the file for read.
        FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read);
        try
        {
            long FileSize = new FileInfo(filename).Length; // File size of file being uploaded.
            // reading the file.
            fs.Position = Offset;
            int BytesRead = 0;
            string msg = "";
            while (Offset != FileSize) // continue uploading the file chunks until offset = file size.
            {
                BytesRead = fs.Read(Buffer, 0, ChunkSize); // read the next chunk 
                // (if it exists) into the buffer. 
                // the while loop will terminate if there is nothing left to read
                // check if this is the last chunk and resize the buffer as needed 
                // to avoid sending a mostly empty buffer 
                // (could be 10Mb of 000000000000s in a large chunk)
                if (BytesRead != Buffer.Length)
                {
                    ChunkSize = BytesRead;
                    byte[] TrimmedBuffer = new byte[BytesRead];
                    Array.Copy(Buffer, TrimmedBuffer, BytesRead);
                    Buffer = TrimmedBuffer; // the trimmed buffer should become the new 'buffer'
                }
                // send this chunk to the server. it is sent as a byte[] parameter, 
                // but the client and server have been configured to encode byte[] using MTOM. 
                bool ChunkAppened = webservice.UploadFile(Path.GetFileName(filename), Buffer, Offset, out msg);
                if (!ChunkAppened)
                {
                    Console.WriteLine("failed to upload. server return error: " + msg);
                    break;
                }
                // Offset is only updated AFTER a successful send of the bytes. 
                Offset += BytesRead; // save the offset position for resume
            }
            Console.WriteLine("successfully uploaded file: " + filename);
        }
        catch (Exception ex)
        {
            Console.WriteLine("failed to upload file: " + ex.Message);
        }
        finally
        {
            fs.Close();
        }
    }
person Christian Holm Jørgensen    schedule 21.10.2015
comment
Это то, что у меня есть (вроде) на данный момент - цикл запросов POST к методу на сервере, проблема в моем коде в том, что сервер отклоняет мои запросы после ~ 100 запросов - person DanielY; 22.10.2015