GZipStream被切断XML的最后一部分 [英] GZipStream is cutting off last part of XML

查看:140
本文介绍了GZipStream被切断XML的最后一部分的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个叫做AddGZip扩展方法,看起来像以下内容:

I have created an extension method called AddGZip which looks like the following:

public static void AddGZip(this HttpResponse response)
{
    response.Filter = new GZipStream(response.Filter, CompressionMode.Compress);
    response.AppendHeader("Content-Encoding", "gzip");
}

这是code非常砍下版本:

This is a very cut down version of the code:

var response = HttpContext.Current.Response;
var request = HttpContext.Current.Request;
var result = File.ReadAllText(path);
if (request.SupportsGZip)
{
  response.AddGZip();
}
response.Write(result);
response.Flush();

当您查看用gzip支持的web浏览器的响应,你得到一个错误这样的:

When you view the response in a web browser with GZip support you get an error like this:

XML解析错误:未关闭的令牌
  地点: HTTP://webserver1/1234.xml
  行号78,第1列:

"XML Parsing Error: unclosed token Location: http://webserver1/1234.xml Line Number 78, Column 1:"

当我认为它基本上错过了最后的&GT的来源;从XML文件的末尾。因此,1或2个字节。

When i view the source it's basically missed out the last > from the end of the XML file. So 1 or 2 bytes.

如果我注释掉AddGZip线正常工作。不过,我真的想支持gzip作为XML可以说是相当大的。

If I comment out the AddGZip Line it works fine. However I really want to support GZip as the XML can be quite large.

有没有人有一个建议给我吗?我试过很多检查的博客,但没有解决方案似乎是在那里为这种类型的错误。

Does anyone have a suggestion for me? I've tried checking lots of blogs but no solution seems to be out there for this type of error.

戴夫

推荐答案

有是一个问题(或者可能是一个很聪明的功能,我还没有看到任何地方对齐)与 DeflateStream GZipStream 基础上 DeflateStream 和继承问题*),其中冲洗可能会丢失数据。

There is an issue (or perhaps a really clever feature that I haven't seen justified anywhere) with DeflateStream (GZipStream builds on DeflateStream and inherits the issue*), where flushing can lose data.

Response.Flush()将刷新过滤器。的解决方案是使用一个包装是知道压缩和解和底层水槽两者,并且仅刷新后者

Response.Flush() will flush the filter. The solution is to use a wrapper that is aware of both the zipping and the underlying sink, and only flushes the latter:

public enum CompressionType
{
    Deflate,
    GZip
}
/// <summary>
/// Provides GZip or Deflate compression, with further handling for the fact that
/// .NETs GZip and Deflate filters don't play nicely with chunked encoding (when
/// Response.Flush() is called or buffering is off.
/// </summary>
public class WebCompressionFilter : Stream
{
    private Stream _compSink;
    private Stream _finalSink;
    public WebCompressionFilter(Stream stm, CompressionType comp)
    {
        switch(comp)
        {
            case CompressionType.Deflate:
                _compSink = new DeflateStream((_finalSink = stm), CompressionMode.Compress);
                break;
            case CompressionType.GZip:
                _compSink = new GZipStream((_finalSink = stm), CompressionMode.Compress);
                break;
        }
    }
    public override bool CanRead
    {
        get
        {
            return false;
        }
    }
    public override bool CanSeek
    {
        get
        {
            return false;
        }
    }
    public override bool CanWrite
    {
        get
        {
            return true;
        }
    }
    public override long Length
    {
        get
        {
            throw new NotSupportedException();
        }
    }
    public override long Position
    {
        get
        {
            throw new NotSupportedException();
        }
        set
        {
            throw new NotSupportedException();
        }
    }
    public override void Flush()
    {
        //We do not flush the compression stream. At best this does nothing, at worse it
        //loses a few bytes. We do however flush the underlying stream to send bytes down the
        //wire.
        _finalSink.Flush();
    }
    public override long Seek(long offset, SeekOrigin origin)
    {
        throw new NotSupportedException();
    }
    public override void SetLength(long value)
    {
        throw new NotSupportedException();
    }
    public override int Read(byte[] buffer, int offset, int count)
    {
        throw new NotSupportedException();
    }
    public override void Write(byte[] buffer, int offset, int count)
    {
        _compSink.Write(buffer, offset, count);
    }
    public override void WriteByte(byte value)
    {
        _compSink.WriteByte(value);
    }
    public override void Close()
    {
        _compSink.Close();
        _finalSink.Close();
        base.Close();
    }
    protected override void Dispose(bool disposing)
    {
        if(disposing)
        {
            _compSink.Dispose();
            _finalSink.Dispose();
        }
        base.Dispose(disposing);
    }
}

这也是值得一提的是支持gzip编码大多数用户代理还支持紧缩编码。虽然采用deflate大小改善negliable(字面意思几个字节),在采用deflate相当好(这正好为COM pressing和DECOM pressing),所以它总是值得利于紧缩对一些建筑交易一些图书馆与HTTP COM pression。

It's also worth noting that most user-agents that support gzip-encoding also support deflate-encoding. While the size improvement with deflate is negliable (literally a few bytes), some libraries on some architecture deals with deflate considerably better (this goes for both compressing and decompressing), so it's always worth favouring deflate over gzip with HTTP compression.

这篇关于GZipStream被切断XML的最后一部分的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆