2009-04-24 33 views
0

我已经JPEG格式图像的流,我试图用HTTP流式传输他们VLC不能流过的JPEG图像的HTTP在C#中

的代码,如果执行以下操作:

public HttpListenerResponse StartListening(String where) 
    { 
     listener = new HttpListener(); 
     listener.Start(); 
     Console.WriteLine("listening on " + where); 
     listener.Prefixes.Add(where); 
     HttpListenerContext context = listener.GetContext(); 
     HttpListenerRequest request = context.Request; 
     // Obtain a response object. 
     HttpListenerResponse response = context.Response; 
     return response; 
    } 
public void StartStream() 
    { 
     HttpListenerResponse response = StartListening("http://localhost:8080/"); 
     MemoryStream mem = null; 

     for (;;) 
     { 
      Bitmap b = generateBitmap(); 
      //pictureBox1.Image = frm.GetFormImage(); 
      byte[] ar = BitmapToArray(b); 


      // Construct a response. 
      byte[] buffer = ar; 
      response.ContentType = "multipart/x-mixed-replace; boundary=--testboundary"; 
      ASCIIEncoding ae = new ASCIIEncoding(); 
      byte[] boundary = ae.GetBytes("\r\n--testboundary\r\nContent-Type: image/jpeg\r\nContent-Length:" + buffer.Length + "\r\n\r\n"); 
      mem = new MemoryStream(boundary); 
      mem.WriteTo(response.OutputStream); 
      mem = new MemoryStream(buffer); 
      mem.WriteTo(response.OutputStream); 
     } 
     mem.Close(); 
     listener.Stop();  

    } 

由于某种原因,如果我尝试打开在Firefox中的流它返回全黑,如果我尝试打开它与VLC我得到“无法打开流”

如果我只流1图像,Firefox没有问题处理它。

韩国社交协会提前, 何塞

回答

3

您可以尝试一个多部分范围的请求。 VLC可能以'块'请求数据,但你的HTTPHandler不提供该功能。以下是一些(冗长的)示例代码。尝试将音乐传输到iPod Touch时遇到类似问题。在浏览器中像魅力一样工作,但没有与Touch一起工作。原来,iPod通过向我的处理程序发出多个请求来请求byte []块,但处理程序没有实现它所需的功能。

我在这里混合了一些我自己的图书馆类,但你会得到足够的图片。

public abstract class MultipartRangeHandler : IHttpHandler 
{ 
    protected const String HEADER_RANGE = "range"; 
    protected const String HEADER_CONTENT_TYPE = "Content-Type"; 
    protected const String HEADER_CONTENT_LENGTH = "Content-Length: "; 
    protected const String HEADER_CONTENT_DISPOSITION = "Content-Disposition"; 
    protected const String HEADER_CONTENT_RANGE = "Content-Range"; 
    protected const String HEADER_BOUNDARY_DELIMETER = "--"; 
    protected const String HEADER_STATUS_PARTIAL_CONTENT = "Partial Content"; 

    private const char COMMA = ','; 
    private const char EQUALS = '='; 
    private const char NEW_LINE = '\n'; 

    protected const String QS_OBJECT_ID = "cid"; 

    public void ProcessRequest(HttpContext context) 
    { 
     if (StringUtils.isNullOrEmpty(context.Request.QueryString[QS_OBJECT_ID])) 
     { 
      sendResponse(400, "400 Bad Request", "No resource was specified in the query string to retrieve.", context); 
     } 
     else 
     { 
      ContentItem contentItem = getContentItem(context.Request.QueryString[QS_OBJECT_ID]); 

      if (contentItem != null) 
      { 
       context.Response.Clear(); 
       context.Response.ClearHeaders(); 
       context.Response.ClearContent(); 

       if (context.Request.Headers[HEADER_RANGE] != null) 
       { 

        string range = context.Request.Headers[HEADER_RANGE]; 
        range = range.Substring(range.LastIndexOf(EQUALS) + 1); 
        bool isMultipartRange = range.Contains(COMMA.ToString()); 

        if (!isMultipartRange) 
        { 
         addHeader(context.Response, HEADER_CONTENT_TYPE, contentItem.MimeType); 
         addHeader(context.Response, HEADER_CONTENT_DISPOSITION, "inline; filename=\"" + contentItem.Filename + "\""); 

         string[] startEnd = range.Split('-'); 

         long startPos; 

         long.TryParse(startEnd[0], out startPos); 

         long endPos; 
         int fileSize = contentItem.FileBytes.Length; 

         if (startEnd.GetUpperBound(0) >= 1 && startEnd[1] != String.Empty) 
         { 
          long.TryParse(startEnd[1], out endPos); 
         } 
         else 
         { 
          endPos = fileSize - startPos; 
         } 

         if (endPos > fileSize) 
         { 
          endPos = fileSize - startPos; 
         } 

         context.Response.StatusCode = 206; 
         context.Response.StatusDescription = HEADER_STATUS_PARTIAL_CONTENT; 
         addHeader(context.Response, HEADER_CONTENT_RANGE, "bytes " + startPos + "-" + endPos + "/" + fileSize); 

         context.Response.BinaryWrite(ByteUtils.subByte(contentItem.FileBytes, (int)startPos, (int)(endPos - startPos) + 1)); 
        } 
        else 
        { 

         string boundary = "waynehartmanansmach"; 
         addHeader(context.Response, HEADER_CONTENT_TYPE, "multipart/byteranges; boundary=" + boundary); 

         List<string[]> ranges = new List<string[]>(); 
         string[] multiRange = range.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries); 
         foreach (string mr in multiRange) 
         { 
          ranges.Add(mr.Split(new string[] { "-" }, StringSplitOptions.RemoveEmptyEntries)); 
         } 

         // process the list of ranges 
         foreach (string[] rangeArray in ranges.ToArray()) 
         { 
          context.Response.Write(HEADER_BOUNDARY_DELIMETER + boundary + NEW_LINE); 
          context.Response.Write(HEADER_CONTENT_TYPE + ": " + contentItem.MimeType + NEW_LINE); 
          context.Response.Write(HEADER_CONTENT_RANGE + ": bytes " + rangeArray[0] + "-" + rangeArray[1] + "/" + contentItem.FileBytes + NEW_LINE + NEW_LINE); 
          long startPos = long.Parse(rangeArray[0]); 
          long endPos = long.Parse(rangeArray[1]); 

          context.Response.BinaryWrite(ByteUtils.subByte(contentItem.FileBytes, (int)startPos, (int)(endPos - startPos) + 1)); 

          context.Response.Write(NEW_LINE); 
          context.Response.Flush(); 
         } 

         context.Response.Write(HEADER_BOUNDARY_DELIMETER + boundary + HEADER_BOUNDARY_DELIMETER + NEW_LINE + NEW_LINE); 
        } 
       } 
       else 
       { 
        context.Response.ContentType = contentItem.MimeType; 
        addHeader(context.Response, HEADER_CONTENT_DISPOSITION, "attachment; filename=\"" + contentItem.Filename + "\""); 
        addHeader(context.Response, HEADER_CONTENT_LENGTH, contentItem.FileBytes.Length.ToString()); 

        context.Response.OutputStream.Write(contentItem.FileBytes, 0, contentItem.FileBytes.Length); 
       } 
      } 
      else 
      { 
       sendResponse(404, "404 Not Found", "The resource requested does not exist.", context);      
      } 
     } 
    } 

    private void sendResponse(int statusCode, String status, String statusMessage, HttpContext context) 
    { 
     System.Text.StringBuilder data = new System.Text.StringBuilder(); 

     data.AppendLine("<html><body>"); 
     data.AppendLine("<h1>"+status+"</h1>"); 
     data.AppendLine("<p>"+statusMessage+"</p>"); 
     data.AppendLine("</body></html>"); 

     byte[] headerData = System.Text.Encoding.ASCII.GetBytes(data.ToString()); 

     context.Response.ContentType = "text/html"; 
     context.Response.StatusCode = statusCode; 
     context.Response.Status = status; 

     addHeader(context.Response, HEADER_CONTENT_LENGTH, headerData.Length.ToString()); 

     //context.Response.AddHeader("Content-Length: ", headerData.Length.ToString()); 
     context.Response.OutputStream.Write(headerData, 0, headerData.Length); 
     context.Response.End(); 
    } 

    protected void addHeader(HttpResponse response, String key, String value) 
    { 
     response.AddHeader(key, value); 
    } 

    protected abstract com.waynehartman.util.web.handlers.multipartrange.ContentItem getContentItem(String objectID); 

    public bool IsReusable 
    { 
     get { return true; } 
    } 
} 
0

设置你的前缀,然后呼叫Start()

从我看到的代码和其他地方,你不能使用HttpListener流数据。 您可能必须将请求转发到另一个将数据写回的本地TCP套接字。

+0

这也行不通 – user361526 2009-04-26 15:14:11