1

我必须创建一个大型 XML 电子表格,现在它似乎已经达到了它可以一次性处理的阈值。

我不确定如何拆分它,所以想知道是否有办法为内部目的增加内存分配?

导致错误的代码如下:

private string RenderViewToString()
{
    using (var writer = new StringWriter())
    {
        var view = ViewEngines.Engines.FindView(_context, _viewName, null).View as RazorView;
        var viewDataDictionary = new ViewDataDictionary<TModel>(_model);
        var viewCtx = new ViewContext(_context, view, viewDataDictionary, new TempDataDictionary(), writer);
        viewCtx.View.Render(viewCtx, writer);
        return writer.ToString();
    }
}

它取决于Render()用户决定从可能的数据组合中下载所有数据时,在丰富数据之前,该文件将大约 55mb 转换为 Excel 文档。现在列已经翻了一番,渲染编写器的代码行正在倒塌。

viewCtx.View.Render(viewCtx, writer);

有没有人有解决方法或知道如何将相关数据拆分为可管理的块而不重新编码?

它从视图模型中获取数据,并且它本身需要跨多个表的 1 到数万行,并且用户在单个 Excel 下载中需要所有这些数据,这会导致问题。

该字符串将输出到此代码:

    protected override void WriteFile(HttpResponseBase response)
    {
        response.Write(RenderViewToString());

    }

但是是否需要返回字符串的整个问题是无关紧要的,因为由于 ViewContext.View.Render(ViewContext, TextWriter) 跌倒,它永远不会走那么远,所以有没有办法将 ViewContext 渲染到没有的东西由于相对较小的文件(60+ MB)导致它出现问题,它会摔倒吗?

我试图允许在 web.config 中使用大文件(一位同事建议这样做),但这没有用。

目前 ViewContext 太大而无法渲染,所以我只需要找到一种方法来渲染它而不使用内置的,有什么想法吗?

- - - 编辑 - - -

非常感谢乔,我修改了您的代码,因为我没有设置 IIS 来使用 HttpContext 标头,但是以下代码可以解决问题:

        HttpContext.Current.Response.Clear();
        using (var writer = new StreamWriter(HttpContext.Current.Response.OutputStream))
        {
            var view = ViewEngines.Engines.FindView(_context, _viewName, null).View
                as RazorView;
            var viewDataDictionary = new ViewDataDictionary<TModel>(_model);
            var viewCtx = new ViewContext(_context,
                view, viewDataDictionary, new TempDataDictionary(), writer);
            viewCtx.View.Render(viewCtx, writer);
        }
        return null;

现在生成一个 70MB 的文件没有问题。

4

1 回答 1

1

您正在将视图输出写入字符串,然后将其写入响应。您可能想要做的是跳过中间人,并将视图直接写入响应。由于该Render方法接受 any TextWriter,因此您可以传递Response.OutputStream给 yourStreamWriter而不是仅仅写入纯字符串。

所以像:

System.Web.HttpContext.Current.Response.Clear();
System.Web.HttpContext.Current.Response.Headers["content-disposition"] = 
    "attachment;filename=somefile.txt"; // or whatever
System.Web.HttpContext.Current.Response.Headers["content-type"] =
    "text/plain"; // or whatever
using (var writer = new StreamWriter(System.Web.HttpContext.Current.Response.OutputStream))
{
    var view = ViewEngines.Engines.FindView(_context, _viewName, null).View
        as RazorView;
    var viewDataDictionary = new ViewDataDictionary<Foo>(_model);
    var viewCtx = new ViewContext(_context, 
        view, viewDataDictionary, new TempDataDictionary(), writer);
    viewCtx.View.Render(viewCtx, writer);
}
return null;
于 2013-10-17T16:32:13.187 回答