C# 解压缩SQL Blob内容并在PushStreamContent.NETCore中返回答案
我正在一个.NET核心服务中开发一个新的API,新的API应该从SQL表中读取一个BLOB,使用DeflateStream解压它。然后将其返回(流式传输)到客户端 为了不消耗太多内存。我将返回一个类型为的响应,这样我就可以直接将sql流复制到响应流中,而无需在内存中加载blob。所以我就这样结束了C# 解压缩SQL Blob内容并在PushStreamContent.NETCore中返回答案,c#,.net,.net-core,sqlclient,deflatestream,C#,.net,.net Core,Sqlclient,Deflatestream,我正在一个.NET核心服务中开发一个新的API,新的API应该从SQL表中读取一个BLOB,使用DeflateStream解压它。然后将其返回(流式传输)到客户端 为了不消耗太多内存。我将返回一个类型为的响应,这样我就可以直接将sql流复制到响应流中,而无需在内存中加载blob。所以我就这样结束了 return this.ResponseMessage(new HttpResponseMessage { Content = new PushStreamCo
return this.ResponseMessage(new HttpResponseMessage
{
Content = new PushStreamContent(async (outStream, httpContent, transportContext) =>
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
await connection.OpenAsync();
using (SqlCommand command = new SqlCommand(query, connection))
{
// The reader needs to be executed with the SequentialAccess behavior to enable network streaming
// Otherwise ReadAsync will buffer the entire BLOB into memory which can cause scalability issues or even OutOfMemoryExceptions
using (SqlDataReader reader = await command.ExecuteReaderAsync(CommandBehavior.SequentialAccess))
{
if (await reader.ReadAsync() && !(await reader.IsDBNullAsync(0)))
{
using (Stream streamToDecompress = reader.GetStream(0))
using (Stream decompressionStream = new DeflateStream(streamToDecompress, CompressionMode.Decompress))
{
// This copyToAsync will take for ever
await decompressionStream.CopyToAsync(outStream);
outStream.close();
return;
}
}
throw new Exception("Couldn't retrieve blob");
}
}
}
},
"application/octet-stream")
});
这里的问题是,将deflateStream复制到响应输出流的步骤将永远像代码中提到的那样进行。虽然我尝试了同样的方法,但将流写入一个文件,而不是复制到resp流,效果非常好
你们能帮我吗??我使用PushStreamContent是不是错了?我应该使用不同的方法吗?问题是我不想在内存中加载整个Blob,我想读取它
并在飞行中解压。blobs,我想利用它。这是PushStreamContent中的死锁,我并不假装理解。但我改变了它
await decompressionStream.CopyToAsync(outStream);
到
解决它
这是完整的报告:
public ResponseMessageResult Get()
{
var data = new string[] { "value1", "value2" };
var jsonData = Newtonsoft.Json.JsonConvert.SerializeObject(data);
var msSource = new MemoryStream(Encoding.UTF8.GetBytes(jsonData));
var msDest = new MemoryStream();
var compressionStream = new DeflateStream(msDest, CompressionMode.Compress);
msSource.CopyTo(compressionStream);
compressionStream.Close();
var compressedBytes = msDest.ToArray();
var query = "select @bytes buf";
var connectionString = "server=localhost;database=tempdb;integrated security=true";
return this.ResponseMessage(new HttpResponseMessage
{
Content = new PushStreamContent(async (outStream, httpContent, transportContext) =>
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
await connection.OpenAsync();
using (SqlCommand command = new SqlCommand(query, connection))
{
command.Parameters.Add("@bytes", SqlDbType.VarBinary, -1).Value = compressedBytes;
// The reader needs to be executed with the SequentialAccess behavior to enable network streaming
// Otherwise ReadAsync will buffer the entire BLOB into memory which can cause scalability issues or even OutOfMemoryExceptions
using (SqlDataReader reader = await command.ExecuteReaderAsync(CommandBehavior.SequentialAccess))
{
if (await reader.ReadAsync() && !(await reader.IsDBNullAsync(0)))
{
using (Stream streamToDecompress = reader.GetStream(0))
{
//var buf = new MemoryStream();
//streamToDecompress.CopyTo(buf);
//buf.Position = 0;
using (Stream decompressionStream = new DeflateStream(streamToDecompress, CompressionMode.Decompress))
{
// This copyToAsync will take for ever
//await decompressionStream.CopyToAsync(outStream);
decompressionStream.CopyTo(outStream);
outStream.Close();
return;
}
}
}
throw new Exception("Couldn't retrieve blob");
}
}
}
},
"application/octet-stream")
});
}
“此copyToAsync将永远持续”是指无限期挂起吗?您确定客户端正在读取到响应流的末尾吗?@DavidBrowne Microsoft,感谢您的回答。是的,它确实无限期地悬挂着。我知道我可以从响应流中读取数据(一次来自SqlReader)。如果我注释掉deflate流,并将响应流复制到outStream,而不进行解压缩,那么它就会工作。但似乎放气流没有从响应中读取。
public ResponseMessageResult Get()
{
var data = new string[] { "value1", "value2" };
var jsonData = Newtonsoft.Json.JsonConvert.SerializeObject(data);
var msSource = new MemoryStream(Encoding.UTF8.GetBytes(jsonData));
var msDest = new MemoryStream();
var compressionStream = new DeflateStream(msDest, CompressionMode.Compress);
msSource.CopyTo(compressionStream);
compressionStream.Close();
var compressedBytes = msDest.ToArray();
var query = "select @bytes buf";
var connectionString = "server=localhost;database=tempdb;integrated security=true";
return this.ResponseMessage(new HttpResponseMessage
{
Content = new PushStreamContent(async (outStream, httpContent, transportContext) =>
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
await connection.OpenAsync();
using (SqlCommand command = new SqlCommand(query, connection))
{
command.Parameters.Add("@bytes", SqlDbType.VarBinary, -1).Value = compressedBytes;
// The reader needs to be executed with the SequentialAccess behavior to enable network streaming
// Otherwise ReadAsync will buffer the entire BLOB into memory which can cause scalability issues or even OutOfMemoryExceptions
using (SqlDataReader reader = await command.ExecuteReaderAsync(CommandBehavior.SequentialAccess))
{
if (await reader.ReadAsync() && !(await reader.IsDBNullAsync(0)))
{
using (Stream streamToDecompress = reader.GetStream(0))
{
//var buf = new MemoryStream();
//streamToDecompress.CopyTo(buf);
//buf.Position = 0;
using (Stream decompressionStream = new DeflateStream(streamToDecompress, CompressionMode.Decompress))
{
// This copyToAsync will take for ever
//await decompressionStream.CopyToAsync(outStream);
decompressionStream.CopyTo(outStream);
outStream.Close();
return;
}
}
}
throw new Exception("Couldn't retrieve blob");
}
}
}
},
"application/octet-stream")
});
}