【问题标题】:Download file (html content) with ServiceStack使用 ServiceStack 下载文件(html 内容)
【发布时间】:2012-08-17 01:35:48
【问题描述】:

我将Service Stack 用于一个简单的网络应用程序。

在这个应用程序中,我需要将一些内容“导出”到 Excel。所以这是我采用的方法:

  1. 我用 jQuery 获取表格的 HTML 内容 a 获取 HTML 内容 表,然后发送到服务。
  2. 服务将内容写入文件(使用一些 CSS)
  3. 使用相同的服务,但使用GET 方法,我读取了文件并 使用ContentType:"application/vnd.ms-excel"进行下载

我在其他时候使用这种方法而不使用服务堆栈,并且效果很好。XLS 文件具有正确的内容和一些颜色。

现在,当我使用GET 方法(即用浏览器访问url)获取文件时,文件内容是错误的。

ServiceStack 允许下载一些格式:html、csv、jsv、json、xml。

html格式显示一个默认的报告页面,唯一有点作用的格式是jsv。

我的问题是:我怎样才能像普通的 html 文件一样下载文件?

一些代码:

public class ExcelService : RestServiceBase<Excel>
{   
    public override object OnGet (Excel request)
    {
        string file = request.nombre;
        //Response.Clear();
        HttpResult res = new HttpResult();
        res.Headers[HttpHeaders.ContentType] = "application/vnd.ms-excel";
        res.Headers[HttpHeaders.ContentDisposition] = "attachment; filename="+file+".xls";
        string archivo = System.IO.File.ReadAllText("tmp/"+file+".html");
        res.Response = archivo;
        return res;
    }
}

提前致谢

【问题讨论】:

    标签: c# servicestack


    【解决方案1】:

    ServiceStack 中的 HttpResult 构造函数作为支持文件下载的重载,例如:

    return new HttpResult(new FileInfo("tmp/"+file+".html"), 
        asAttachment: true, 
        contentType: "application/vnd.ms-excel");
    

    这将设置文件下载所需的ContentDisposition HTTP 标头。

    创建自己的 Http 结果

    要对 HttpOutput 进行更细粒度的控制,您还可以创建自己的 Result 类。以下是从customized responses in ServiceStack question 下载 Excel 电子表格的示例:

    public class ExcelFileResult : IHasOptions, IStreamWriterAsync
    {
        private readonly Stream _responseStream;
        public IDictionary<string, string> Options { get; private set; }
    
        public ExcelFileResult(Stream responseStream)
        {
            _responseStream = responseStream;
    
            Options = new Dictionary<string, string> {
                 {"Content-Type", "application/octet-stream"},
                 {"Content-Disposition", ""attachment; filename=\"report.xls\";"}
             };
        }
    
        public async Task WriteToAsync(Stream responseStream, CancellationToken token = default)
        {
            if (_responseStream == null) 
                return;
    
            await _responseStream.CopyToAsync(responseStream, token);
            await responseStream.FlushAsync(token);
        }
    }
    

    【讨论】:

    • 很好的例子,为我工作。值得注意的是,上面这个类是服务操作返回的响应类。
    • 你应该如何用 IStreamWriterAsync 更新这个答案?
    • @mythz 谢谢。在 Web 环境(.NET Framework 4.6)中,我不得不将“CopyToAsync”替换为“WriteToAsync”。否则,内容是长度为 0 的文件(即使使用“CopyToAsync”进行单元测试返回具有预期长度的流)。
    • @labilbe 奇怪,可能你的_responseStream 位置没有设置为0
    • @mythz 赞!!这就是原因。我印象深刻!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-04
    • 2013-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-01
    • 2020-08-06
    相关资源
    最近更新 更多