2014-09-18 8 views
0

У нас есть сервер на работе, который мы можем запросить для фотографий с помощью веб-службы. Человек, который поддерживает сервер, является разработчиком Java, но мне нужно иметь возможность запрашивать сервер с помощью dotNET, поскольку я использую SDK для интеграции с существующим приложением, которое мы запускаем, и она неохотно/не может помочь с dotNET.HttpWebResponse с несколькими частями

Это моя просьба к фото (обратите внимание на требуемый сертификат): -

private WebResponse Request() 
{ 
    ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(Validate); 
    X509Certificate certificate = X509Certificate.CreateFromCertFile("wmbuat.crt"); 

    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(server.Text); 
    request.Headers.Add("SOAP:Action"); 
    request.ContentType = "text/xml"; 
    request.Accept = "text/xml"; 
    request.Method = "POST"; 
    request.ClientCertificates.Add(certificate); 

    GetXml().Save(request.GetRequestStream()); 
    return request.GetResponse(); 
} 

private static Boolean Validate(Object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors) 
{ 
    return true; 
} 

Я могу обращаться к серверу не драм, но HttpWebResponse состоит из двух частей в одном потоке - в XML-части, содержащую информацию о фотографии и двоичной части, которая является JPEG. Например: -

--WMBMIME2Boundaryurn_uuid_C123 
Content-Type: text/xml; charset=utf-8 
Content-Transfer-Encoding: binary 
Content-ID: <0.urn:uuid:C123[email protected]> 

<NS1:Envelope xmlns:NS1="http://schemas.xmlsoap.org/soap/envelope/">...</NS1:Envelope> 
--WMBMIME2Boundaryurn_uuid_C123 
Content-Type: application/octet-stream 
Content-Transfer-Encoding: binary 
Content-ID: <987> 

yoya..JFIF... 

Я видел пару вопросов здесь в связи с этим, но я, кажется, не быть в состоянии использовать сертификат с этими библиотеками. Есть ли способ обернуть выходной поток, чтобы получить части как отдельные объекты? Я рад, что это просто String и byte [], и я могу преобразовать его в XML и Image самостоятельно.

Я попытался с помощью StreamReader и чтения на вторую пустую строку, которая где начинается двоичные данные, а затем читают остаток от исходного потока в файл, но это не работает: -/

Любая помощь будет принята с благодарностью.

Спасибо.

ответ

0

Для тех, кто пытается достичь чего-то подобного, я сделал небольшое обходное решение для этого доказательства концепции. Это не самый эффективный код, но он получает работу в краткосрочной перспективе, когда я работаю над улучшением его между ними все остальное я сделать, чтобы получить :-)

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.IO; 
using System.Linq; 
using System.Net; 
using System.Text; 
using System.Threading.Tasks; 
using System.Windows.Forms; 
using System.Xml; 

namespace COPS_Photo_Viewer 
{ 
    public partial class CPV : Form 
    { 
     public CPV() 
     { 
      InitializeComponent(); 

      textIP.Text = Dns.GetHostAddresses(Dns.GetHostName())[0].MapToIPv4().ToString(); 
      textID.Text = System.Security.Principal.WindowsIdentity.GetCurrent().Name; 
      textMachine.Text = Dns.GetHostName(); 
      textApplication.Text = Application.ProductName; 
     } 

     private Image ExtractImage(byte[] binary) 
     { 
      int start = 0; 
      for (; start < binary.Length; ++start) 
       if (((char)binary[start]) == 'ÿ') 
        break; 

      byte[] image = new byte[binary.Length - start]; 
      for (int index = start; index < binary.Length; ++index) 
       image[index - start] = binary[index]; 

      return Bitmap.FromStream(new MemoryStream(image)); 
     } 

     private void GetImage(Object sender, EventArgs args) 
     { 
      WebResponse response = Request(); 
      byte[] input = ReadStream(response.GetResponseStream()); 
      photograph.Image = ExtractImage(input); 
     } 

     private XmlDocument GetXml() 
     { 
      XmlDocument xml = new XmlDocument(); 
      xml.LoadXml(...); 
      return xml; 
     } 

     private byte[] ReadStream(Stream stream) 
     { 
      Queue<byte> input = new Queue<byte>(); 
      byte[] buffer = new byte[1]; 

      for (int read = stream.ReadByte(); read >= 0; read = stream.ReadByte()) 
       input.Enqueue((byte)read); 

      return input.ToArray<byte>(); 
     } 

     private WebResponse Request() 
     { 
      ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(Validate); 
      System.Security.Cryptography.X509Certificates.X509Certificate certificate = 
      System.Security.Cryptography.X509Certificates.X509Certificate.CreateFromCertFile("wmbuat.crt"); 

      HttpWebRequest request = (HttpWebRequest)WebRequest.Create(textURL.Text); 
      request.Headers.Add("SOAP:Action"); 
      request.ContentType = "text/xml"; 
      request.Accept = "text/xml"; 
      request.Method = "POST"; 
      request.ClientCertificates.Add(certificate); 

      GetXml().Save(request.GetRequestStream()); 
      return request.GetResponse(); 
     } 

     private static Boolean Validate(Object sender, System.Security.Cryptography.X509Certificates.X509Certificate certificate, System.Security.Cryptography.X509Certificates.X509Chain chain, System.Net.Security.SslPolicyErrors errors) 
     { 
      return true; 
     } 
    } 
} 

GetImage сначала запускается, когда кнопка на форму нажата. Как только результат получается, он превращает поток ответов в массив байтов, затем ищет первый экземпляр «ÿ» (который только когда-либо появится в начале JPEG в нашей ситуации), а затем превращает оставшуюся часть массив в MemoryStream, который затем превращается в изображение.

Очевидно, что чтение одного байта за раз в очередь не самое лучшее, но, к счастью, это происходит по сети, поэтому (по крайней мере, на этой начальной стадии разработки) это не проблема, и фото все еще загружается мгновенно.

0

Используемые классы клиентов и запросов относятся к пространству имен System.Net, который абстрагирует вас немного меньше, чем некоторые из более новых классов из пространства имен System.Net.Http. Как и все новое, существует меньше документации и примеров, но в этом конкретном случае я думаю, что использование классов клиентов, поставляемых с «Microsoft WebAPI Framework», принесет вам пользу.

В частности, класс ответ в рамках WebAPI называется HttpResponseMessage, и он имеет свойство

HttpResponseMessage response = ... 
HttpContent content = response.Content; 
if(content is MultipartContent) 
{ 
    // loop through parts 
} 

Вы можете найти более подробную документацию по этому пространству имен здесь:

http://www.asp.net/web-api/overview/advanced/calling-a-web-api-from-a-net-client

One разбойник может находиться на старой версии .NET. Я считаю, что для WebAPI 2 требуется последняя и самая большая версия 4.5, но вы можете найти ее для версии 4. Я не работал с предыдущей версией, но я полагаю, что разбор, который они делают, чтобы разделить его на несколько частей контента, тривиальный.

+0

Hi welegan, Благодарим за это, но да, как вы упомянули, у меня есть доступ к dotNET 4.0 (технически большая часть компьютеров на нашем рабочем месте работает на 3.5, но я могу обновить любой из них до 4.0 по мере необходимости). Мы все еще на XP, поэтому я не могу установить 4.5. – SignalOne

+0

yikes, ладно, удачи тогда, найдя хороший способ разобрать http mime parts, я уверен, что для этого есть учебники, но есть много исправлений iirc. – welegan

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