【问题标题】:IEnumerable<string> to Stream for FileStreamResultIEnumerable<string> 为 FileStreamResult 流式传输
【发布时间】:2014-05-14 20:30:12
【问题描述】:

我有一个IEnumerable&lt;string&gt;,它是根据方法中的yield 语句“流式传输”的。现在我想将此枚举转换为Stream 以将其用作流式传输结果。有什么想法可以做到这一点吗?

我最终想要做的是从 ASP.NET 控制器操作中将Stream 作为FileStreamResult 返回。此结果应作为下载流式传输到客户端。

我不想做的是在返回结果之前将IEnumerable 的全部内容写入流。这将消除流概念的整体意义。

【问题讨论】:

  • 为什么要使用FileStreamResult,具体来说?编写自己的ActionResult 指定内容类型/内容处置并按照您的意愿行事不是很有意义吗?注意:您可能要考虑的一个问题是:如何提前设置 content-length 标头,而不需要对数据进行迭代和编码

标签: c# .net asp.net-mvc stream ienumerable


【解决方案1】:

你必须创建你的 ActionResult 类来实现惰性求值。您已经创建了 ContentResultFileStreamResult 类的组合,以实现类似 FileStreamResult 的行为,并能够设置结果编码。好的起点是FileResult抽象类:

public class EnumerableStreamResult : FileResult
{

    public IEnumerable<string> Enumerable
    {
        get;
        private set;
    }

    public Encoding ContentEncoding
    {
        get;
        set;
    }

    public EnumerableStreamResult(IEnumerable<string> enumerable, string contentType)
        : base(contentType)
    {
        if (enumerable == null)
        {
            throw new ArgumentNullException("enumerable");
        }
        this.Enumerable = enumerable;
    }

    protected override void WriteFile(HttpResponseBase response)
    {
        Stream outputStream = response.OutputStream;
        if (this.ContentEncoding != null)
        {
            response.ContentEncoding = this.ContentEncoding;
        }
        if (this.Enumerable != null)
        {
            foreach (var item in Enumerable)
            {

                //do your stuff here
                response.Write(item);
            }
        }
    }
}

【讨论】:

  • 太棒了。这正是我想要的!在编写了 n 个可枚举条目之后,我在 WriteFile 方法中添加了一个 response.Flush() ......并添加了一些错误修复。非常感谢!
  • @Matthias - “并添加了一些错误修复”。我现在正在写类似的东西,上面的例子对我有用。我很想知道你修复了什么错误,这样我就不会遇到同样的问题。
  • @AndyNichols 在 WriteFile() 中我首先做了一个 response.Flush()。此外,我在 foreach 循环中逐块添加了 Flush()。否则下载对话框将不会更新其进度,并且 UI 被阻止(在我的情况下)。
【解决方案2】:

返回一个FileStreamResult,传入enumerable.ToStream():

public IActionResult Get()
{
    IEnumerable<string> lines = GetLines();
    Stream stream = lines.ToStream();
    return File(stream, "text/csv");
}

ToStream() 在EnumerableToStream 包中实现。

【讨论】:

    【解决方案3】:

    我认为您可以在此使用它首先将您的字符串转换为字节数组,然后再使用内存流

    string sourceFile = System.Web.HttpContext.Current.Server.MapPath(Path.Combine("/", "yourAddress"));
    byte[] byteArray = System.IO.File.ReadAllBytes(sourceFile);
    
    MemoryStream mem;
            using (mem = new MemoryStream())
            {
                mem.Write(byteArray, 0, (int)byteArray.Length);
                return mem;
            }
    

    【讨论】:

    • 为什么不使用using (var mem = new MemoryStream()) 而不是using (mem = new MemoryStream())?您现在可以删除MemoryStream mem;
    • 我的问题是:“我不想做的是在返回结果之前将 IEnumerable 的全部内容写入流。这将消除流概念的整体意义。”
    猜你喜欢
    • 2014-03-29
    • 1970-01-01
    • 2010-11-12
    • 1970-01-01
    • 2013-08-14
    • 2013-01-25
    • 1970-01-01
    • 2011-06-11
    • 1970-01-01
    相关资源
    最近更新 更多