C# 我可以将压缩的Gzip流复制到另一个流吗?

C# 我可以将压缩的Gzip流复制到另一个流吗?,c#,asp.net-core,stream,compression,C#,Asp.net Core,Stream,Compression,我正在使用ASP.NET Core 2.0为某个站点编写代理。如果代理只需将HttpResponseMessage重新翻译到浏览器中,那么它就可以正常工作。我的代理基于示例。但我需要对网站内容进行一些更改,例如,某些href包含绝对引用。因此,当我从我的代理中单击它们时,我会进入原始站点,这是一个问题 我可以使用我找到的方式访问目标页面内容。但是,当我试图将更改的内容复制到HttpResponse.Body时,我遇到了NotSupportedException,消息是gzip流不支持读取。我的代

我正在使用ASP.NET Core 2.0为某个站点编写代理。如果代理只需将
HttpResponseMessage
重新翻译到浏览器中,那么它就可以正常工作。我的代理基于示例。但我需要对网站内容进行一些更改,例如,某些href包含绝对引用。因此,当我从我的代理中单击它们时,我会进入原始站点,这是一个问题

我可以使用我找到的方式访问目标页面内容。但是,当我试图将更改的内容复制到
HttpResponse.Body
时,我遇到了
NotSupportedException
,消息是
gzip流不支持读取。我的代码如下:

public static async Task CopyProxyHttpResponse(this HttpContext context, HttpResponseMessage responseMessage)
{
    if (responseMessage == null)
    {
        throw new ArgumentNullException(nameof(responseMessage));
    }

    var response = context.Response;
    response.StatusCode = (int)responseMessage.StatusCode;

    //work with headers

    using (var responseStream = await responseMessage.Content.ReadAsStreamAsync())
    {
        string str;
        using (var gZipStream = new GZipStream(responseStream, CompressionMode.Decompress))
        using (var streamReader = new StreamReader(gZipStream))
        {
            str = await streamReader.ReadToEndAsync();
            //some stings changes...
        }
        var bytes = Encoding.UTF8.GetBytes(str);
        using (var msi = new MemoryStream(bytes))
        using (var mso = new MemoryStream())
        {
            using (var gZipStream = new GZipStream(mso, CompressionMode.Compress))
            {
                await msi.CopyToAsync(gZipStream);
                await gZipStream.CopyToAsync(response.Body, StreamCopyBufferSize, context.RequestAborted);
            }
        }
        //next string works, but I don't change content this way
        //await responseStream.CopyToAsync(response.Body, StreamCopyBufferSize, context.RequestAborted);
    }
}
经过一些搜索,我发现,在压缩成
gzip流之后,
gzip流.CanRead
是假的,如果
CompressionMode
Compressed
,它似乎总是假的。我还尝试将
msi
复制到
response.Body
,它不会引发异常,但在浏览器中我得到一个空页面(浏览器控制台中网络中的文档响应也是空的)


是否可以将压缩的
gzip流
复制到另一个
中,或者我的方法完全错误?

gzip流不是直接复制的。您的mso流正在保存压缩数据

但您可以完全删除mso流,并将msi流复制到响应。正文:

using (var msi = new MemoryStream(bytes))
{
    using (var gZipStream = new GZipStream(response.Body, CompressionMode.Compress)) //<-- declare your response.Body as the target for the compressed data 
    {
        await msi.CopyToAsync(gZipStream, StreamCopyBufferSize, context.RequestAborted); //copy the msi stream to the response.Body through the gZipStream
    }
}
使用(var msi=新内存流(字节))
{

使用(var gZipStream=new gZipStream(response.Body,CompressionMode.Compress))//到目前为止它工作得很好,我必须在晚上测试它,但希望它足以解决它(我几乎不希望它).有趣的方式..我实际上将数据复制到
gZipStream
,它们以某种方式到达
Body
。@QuarK流从不保存任何数据。它们只帮助您从一个源到另一个源读取、写入和/或处理数据。就像FileStream专门用于文件访问一样,gZipStream专门用于(de-)源之间的压缩。在您的示例中,GZipStream“动态”压缩msi流中的数据,同时写入response.Body。