2012-11-05 2 views
1

Я пытаюсь написать приложение, которое будет работать с платформой управления носителями с открытым исходным кодом, Kaltura. Kaltura предоставила некоторые клиентские библиотеки C#, которые общаются с их веб-API, и я смог поговорить с сервером и успешно загрузить видео. Проблема, с которой я сталкиваюсь, заключается в том, что когда файлы достигают определенного размера, я получаю исключение из памяти и сбой программы. Я хотел бы попытаться исправить эту проблему и представить улучшенный код обратно в проект с открытым исходным кодом, но будучи новым для C#, я не с того, с чего начать. Есть ли лучший способ, чем memystream делать то, что они делают?Получение исключения из памяти с memystream

Заранее спасибо.

//Problematic code 

private void PostMultiPartWithFiles(HttpWebRequest request, KalturaParams kparams, KalturaFiles kfiles) 
    { 
     string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x"); 
     request.ContentType = "multipart/form-data; boundary=" + boundary; 

     // use a memory stream because we don't know the content length of the request when we have multiple files 
     MemoryStream memStream = new MemoryStream(); 


     byte[] buffer; 
     int bytesRead = 0; 

     StringBuilder sb = new StringBuilder(); 
     sb.Append("--" + boundary + "\r\n"); 
     foreach (KeyValuePair<string, string> param in kparams) 
     { 
      sb.Append("Content-Disposition: form-data; name=\"" + param.Key + "\"" + "\r\n"); 
      sb.Append("\r\n"); 
      sb.Append(param.Value); 
      sb.Append("\r\n--" + boundary + "\r\n"); 
     } 

     buffer = Encoding.UTF8.GetBytes(sb.ToString()); 
     memStream.Write(buffer, 0, buffer.Length); 

     foreach (KeyValuePair<string, FileStream> file in kfiles) 
     { 
      sb = new StringBuilder(); 
      FileStream fileStream = file.Value; 
      sb.Append("Content-Disposition: form-data; name=\"" + file.Key + "\"; filename=\"" + Path.GetFileName(fileStream.Name) + "\"" + "\r\n"); 
      sb.Append("Content-Type: application/octet-stream" + "\r\n"); 
      sb.Append("\r\n"); 

      // write the current string builder content 
      buffer = Encoding.UTF8.GetBytes(sb.ToString()); 
      memStream.Write(buffer, 0, buffer.Length); 

      // write the file content 
      buffer = new Byte[checked((uint)Math.Min(4096, (int)fileStream.Length))]; 
      bytesRead = 0; 
      while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0) 
       memStream.Write(buffer, 0, bytesRead); 

      buffer = Encoding.UTF8.GetBytes("\r\n--" + boundary + "\r\n"); 
      memStream.Write(buffer, 0, buffer.Length); 
     } 

     request.ContentLength = memStream.Length; 

     Stream requestStream = request.GetRequestStream(); 
     // write the memorty stream to the request stream 
     memStream.Seek(0, SeekOrigin.Begin); 
     buffer = new Byte[checked((uint)Math.Min(4096, (int)memStream.Length))]; 
     bytesRead = 0; 
     while ((bytesRead = memStream.Read(buffer, 0, buffer.Length)) != 0) 
      requestStream.Write(buffer, 0, bytesRead); 

     requestStream.Close(); 
     memStream.Close(); 
    } 
+4

Похоже, что вы загружаете весь набор видео в поток вашей памяти ... Это может (обязательно) вызвать вашу исключение из памяти. Вы не должны буферизировать все это в памяти, а просто копировать его прямо в 'RequestStream' –

+1

. Это какая-то операция POST? Очевидная проблема будет заключаться в том, что код не использует поток запросов напрямую, а занимает обходную линию памяти. Это связано с ошибкой с большими файлами. Таким образом, вместо того, чтобы писать в Memorystream, пишите в поток запросов и смотрите, где это вам. – flq

ответ

0

Вот версия более или менее, как бы я ее написал. Он только компилируется, но я его не тестировал. Обратите внимание на использование StreamWriter и прямое использование потока запросов ...

public class SendStuff 
    { 
     private readonly HttpWebRequest _request; 
     private readonly Dictionary<string, string> _kparams; 
     private readonly Dictionary<string, FileStream> _kfiles; 
     readonly string _boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x"); 

     public SendStuff(
      HttpWebRequest request, 
      Dictionary<string, string> kparams, 
      Dictionary<string, FileStream> kfiles) 
     { 
      _request = request; 
      _kparams = kparams; 
      _kfiles = kfiles; 
      _request.ContentType = "multipart/form-data; boundary=" + _boundary; 
     } 

     public void Do() 
     { 

      // Based on HTTP 1.1, if the server can determine the content length, it need not insist on 
      // us sending one. If you are talking 
      // to a "special" server, construct the headers beforehand, measure their length 
      // and identify the file lengths of the files to be sent. 

      using (var reqStream = _request.GetRequestStream()) 
      using (var writer = new StreamWriter(reqStream)) 
      { 
       writer.NewLine = "\r\n"; 
       WriteBoundary(writer); 
       WriteParams(writer); 

       foreach (var file in _kfiles) 
       { 
        writer.WriteLine("Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"", 
         file.Key, 
         Path.GetFileName(file.Value.Name)); 
        writer.WriteLine("Content-Type: application/octet-stream"); 
        writer.WriteLine(); 

        WriteTheFileContent(reqStream, file.Value); 

        WriteBoundary(writer); 
       } 
      } 
     } 

     private static void WriteTheFileContent(Stream reqStream, Stream fileStream) 
     { 
      int bytesRead; 
      var buffer = new byte[4096]; 
      while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0) 
       reqStream.Write(buffer, 0, bytesRead); 
     } 

     private void WriteParams(StreamWriter writer) 
     { 
      foreach (var param in _kparams) 
      { 
       writer.WriteLine("Content-Disposition: form-data; name=\"{0}\"", param.Key); 
       writer.WriteLine(); 
       writer.WriteLine(param.Value); 
       WriteBoundary(writer); 
      } 
     } 

     private void WriteBoundary(TextWriter writer) 
     { 
      writer.WriteLine("\r\n--{0}\r\n", _boundary); 
     } 
    } 
+0

Спасибо. Это полезно. Мне удалось передать данные, хотя я думаю, что у меня что-то не так, как все отправляется. В конце концов, я смогу его получить. – user1549568

Смежные вопросы