【问题标题】:How To: Save a file from a webservice without stopping the page from rendering如何:在不停止渲染页面的情况下从 Web 服务保存文件
【发布时间】:2023-03-27 08:40:02
【问题描述】:

我有一个控制器,它有两个页面,索引和下载,当单击下载时,它会从服务中检索一个字节 [],然后我使用 Response.BinaryWrite 来保存文件。这样做的问题是,当使用 Response.Clear 时,它会停止渲染下载页面,但会成功下载文件。有没有办法下载文件并渲染页面?

我正在使用 .NET 4、ASP、Monorail Castle、C#

我知道通过使用 MVC,我可以使用 ActionResult 和 FileResult 作为我的视图的返回类型,但是我只能使用 Monorail Castle,因为它是我最近拥有的一个现有项目并且没有改变它的技术的重要性。

下面是我的示例代码

public class MyController : Controller
{
    public void Index()
    {
        PropertyBag["includeZeroBalances"] = false;
        PropertyBag["toDate"] = DateTime.Today.ToShortDateString();
    }

    public void Download(bool includeZeroBalances, DateTime toDate)
    {
        MyProxy proxy = GetProxy();
        byte[] file = proxy.GetFile(includeZeroBalance, toDate);
        Response.Clear();
        Response.ContentType = "application/zip";
        Response.AppendHeader("Content-Disposition", "attachment; filename="TestFileName.zip");
        Response.BinaryWrite(file);
    }
}

这里是索引页面

${Form.FormTag({@action: 'Download'})}
    <table>
        <tr>
            <td>${Form.LabelFor("toDate", "To Date (yyyy/mm/dd):")}</td>
            <td><input type="text" id="toDate" name="toDate" value="${?toDate}" /></td>
        </tr>
        <tr>
            <td>${Form.LabelFor("includeZeroBalances", "Include Zero Balances:")}</td>
            <td>${Form.CheckboxField("includeZeroBalances")}</td>
        </tr>
        <tr>
            <td>&nbsp;</td>
            <td>${Form.Submit("Download", {@class: 'submitb'})}</td>
        </tr>
    </table>
${Form.EndFormTag()}

这里是下载页面

<table>
    <tr>
        <td>Your file has been downloaded successfully</td>
    </tr>
</table>

【问题讨论】:

    标签: c# asp.net download castle-monorail


    【解决方案1】:

    执行此操作的“正确”方法是使用多部分响应,不幸的是some browsers don't support them

    您可以做的是像 sourceforge 和其他网站那样使用元刷新。有关替代方案,请参阅以下问题:

    【讨论】:

    • 您好 Mauricio,感谢您提供的链接和见解。不幸的是,这并不完全是我想要的。
    • @ROFFELPOMP :嗯,这正是你在回答中所做的。
    【解决方案2】:

    我想出的答案并不像我希望的那样通用,但这个解决方案很实用。

    public class MyController : Controller
    {
        public void Index()
        {
            PropertyBag["includeZeroBalances"] = false;
            PropertyBag["toDate"] = DateTime.Today.ToShortDateString();
        }
    
        public void Download(bool includeZeroBalances, DateTime toDate)
        {
            MyProxy proxy = GetProxy();
            byte[] file = proxy.GetFile(includeZeroBalance, toDate);
            PropertyBag["downloadurl"] = "data:application/zip;base64," + System.Convert.ToBase64String(file);
        }
    }
    

    这里是索引页面

    ${Form.FormTag({@action: 'Download'})}
        <table>
            <tr>
                <td>${Form.LabelFor("toDate", "To Date (yyyy/mm/dd):")}</td>
                <td><input type="text" id="toDate" name="toDate" value="${?toDate}" /></td>
            </tr>
            <tr>
                <td>${Form.LabelFor("includeZeroBalances", "Include Zero Balances:")}</td>
                <td>${Form.CheckboxField("includeZeroBalances")}</td>
            </tr>
            <tr>
                <td>&nbsp;</td>
                <td>${Form.Submit("Download", {@class: 'submitb'})}</td>
            </tr>
        </table>
    ${Form.EndFormTag()}
    

    这里是下载页面

    <table>
        <tr>
            <td>Your file has been generated successfully. <a href="${downloadurl}">Click here</a> to download your file</td>
        </tr>
    </table>
    

    您还可以添加 javascript 以在新窗口中自动下载文件。

    document.Ready(function()
    {
        window.open("${downloadurl}");
    });
    

    使用这种方法保存文件的优点: 没有文件保存在服务器上。 下载超过 300kb 的文件时开销略低 您不会覆盖响应数据,因此视图将照常呈现。

    使用这种方法保存文件的缺点: 不够通用,无法在任何版本的任何浏览器上使用。 如果用于静态文件,当文件更改时,由于文件内容嵌入在 uri 中,因此必须重新生成 uri

    我希望这可以帮助其他似乎被困在同一问题上的人。我在许多板上都看到过这种类型的问题,没有直接的解决方案。

    【讨论】:

      猜你喜欢
      • 2015-05-25
      • 1970-01-01
      • 2018-09-19
      • 2013-09-07
      • 2018-12-31
      • 1970-01-01
      • 2013-08-06
      • 2012-08-09
      • 1970-01-01
      相关资源
      最近更新 更多