Résumé
Twitter
Work Blog
Guestbook
Login

Obtaining Response.OutputStream.Length...

Share |
<= Previous Post | Next Post =>

In ASP.NET, the Response.OutputStream is write-only. As a result, if you attempt to read the length of the response output at any point in stage in the page events, you get the "NotSupportedException". Taking a page from the book of guys who wrote compression filters that compress the response output on-the-fly, I discovered that I could access the length of the response as it is written...

Basically, I wrote a custom class that inherits "Stream" and overrides all of the appropriate stream's methods/properties. The default constructor accepts a Stream object and stores it in a private variable, so the overridden methods/properties all expose the underlying stream's methods/properties. Example: override public bool CanRead { get { return this._stream.CanRead; } }. I declared a "private long _length = 0;" variable and set the value in my stream's "SetLength" method and update it in the "Write" method using the "count" parameter, ensuring the length always reflects the data length. In the "Close" method, I use "base.Close();" and then I can do whatever I want with my private "_length" variable, which contains the length of the response's output stream.

Once I had the class above, I used the following code in the page's "OnLoad" event:
this.Response.Filter = new ObserveResponseLengthStream(this.Response.Filter);


Per Jorge Pereyra's request, here is the code for "write, setLength, flush and seek":


class ObserveResponseLengthStream : Stream
{
   private Stream _stream = null;
   private long _length = 0;
   public ObserveResponseLengthStream(Guid urlKey, 
      Stream stream)
   {
      this._stream = stream;
   }

   public override long Seek(long offset, 
      SeekOrigin origin)
   {
      return this._stream.Seek(offset, origin);
   }

   public override void Flush()
   {
      this._stream.Flush();
   }

   public override void SetLength(long value)
   {
      this._stream.SetLength(value);
      this._length = value;
   }

   public override void Write(byte[] buffer, 
      int offset, 
      int count)
   {
      this._stream.Write(buffer, offset, count);
      this._length += (long)count;
   }

   public override void Close()
   {
      try
      {
         this._stream.Close();
      }
      catch { }

      base.Close();

      try
      {
         /*now you know the actual length 
           of the response in this._length,
           so do whatever you want with it*/
      }
      catch (Exception ex)
      {
         //make sure your exceptions are handled!
      }
   }

   /*...all the other code simply exposes the 
     _stream's properties and methods...*/
}

Share |
<= Previous Post | Next Post =>

Comments

Submit New Comment

*Your e-mail is not shared with others. If provided, I simply use it as a method of contacting you about your comment(s) on this website. If you have a direct question, simply contact me.

*Cannot contain HTML and NO SPAM!

Could you post the code for write, setLength, flush and seek