2013-09-16 2 views
2

Я возвращаю поток данных из службы ServiceStack следующим образом. Обратите внимание, что мне нужно сделать это таким образом, а не способами, указанными here, потому что мне нужно выполнить некоторую очистку после того, как данные были записаны в выходной поток.Сжатие потока ServiceStack

using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read)) 
{ 
    fs.WriteTo(Response.OutputStream); 
} 
Response.EndRequest(); 
...cleanup code... 

Сжатия осуществляются в других услугах, которые возвращают простые DTOs с помощью ServiceRunner аналогичной this answer. Однако ответ на поток выше никогда не попадает в этот код, поскольку объект ответа в OnAfterExecute всегда равен нулю. Я могу вручную сжать результат внутри метода службы следующим образом, но для этого требуется много настроек, чтобы определить, требуется ли и какое сжатие, и вручную настроить правильные заголовки HTTP (опущены ниже).

var outStream = new MemoryStream(); 
using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read)) 
using (var tinyStream = new GZipStream(outStream, CompressionMode.Compress)) 
{ 
    fs.CopyTo(tinyStream); 
    outStream.WriteTo(Response.OutputStream); 
} 
Response.EndRequest(); 
...cleanup code... 

Есть ли способ в ServiceStack, чтобы справиться с этим сжатие для меня подобно тому, как он работает с ServiceRunner?

ответ

2

Я не совсем уверен, что вам нравится в том, как ServiceStack обрабатывает сжатие в ServiceRunner. Это потому, что это глобально через API ServiceStack?

Для примера, я думаю, что-то вроде ниже работ и отвечает вашим потребностям, чтобы выполнить некоторую очистку после того, как данные были записаны в выходной поток ...

public class FStreamService : Service 
{ 
    public object Get(FStream request) 
    { 
     var filePath = @"c:\test.xml"; 
     var compressFileResult = new CompressedFileResult(filePath); //CompressedResult in ServiceStack.Common.Web.CompressedFileResult 
     compressFileResult.WriteTo(Response.OutputStream); 
     Response.EndRequest(); 
     // ...cleanup code... 
    } 
} 

на основе комментариев обновления выше компрессию с помощью некоторых расширений ServiceStack

public object Get(FStream request) 
{ 
    var filePath = @"c:\test.xml"; 
    using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read)) 
    { 
     var compressedBtyes = fs.ToUtf8String().Compress(this.RequestContext.CompressionType); 
     new CompressedResult(compressedBtyes).WriteTo(Response.OutputStream);   
    } 
    Response.EndRequest(); 
     // ...cleanup code... 
} 

Если вы хотите в ServiceRunner что-то вроде этого должно работать ...

public override object OnAfterExecute(IRequestContext requestContext, object response) 
{ 
    var resp = requestContext.Get<IHttpResponse>(); 
    response = requestContext.ToOptimizedResult(requestContext.Get<IHttpResponse>().OutputStream);  

    return base.OnAfterExecute(requestContext, response); 
} 

+0

Я не был в состоянии получить либо из тех, чтобы работать должным образом. CompressedFileResult предполагает, что данные уже сжаты (https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.Common/Web/CompressedFileResult.cs#L62). Расширение ToOptimizedResult не работает, потому что этот метод [ожидает DTO] (https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack/RequestContextExtensions.cs#L20), а не поток. Я думаю, что я могу использовать 'CompressedFileResult' для обработки заголовков, но мне придется вручную определить, нужно ли сжимать и выполнять сжатие. –

+0

Не совсем уверен в конкретной причине, которую вы хотите написать непосредственно в OutputStream, но можете ли вы создать/убрать экземпляр CompressedResult, выполнить очистку и вернуть экземпляр CompressedResult? – paaschpa

Смежные вопросы