【问题标题】:How to prevent extra request if pdf requested refreshed in browser如果pdf请求在浏览器中刷新,如何防止额外请求
【发布时间】:2016-10-14 19:36:22
【问题描述】:

ASP.NET MVC 4 控制器返回 pdf:

public class ReportController : ControllerBase
{

    public ActionResult Pdf()  {

        byte[] result = CreatePDF();
        var ms = new MemoryStream(result);
        return new FileStreamResult(ms, "application/pdf");
    }
 }

结果显示在 Chrome 浏览器窗口中。 如果调用此 url 或在浏览器中按下刷新按钮,Chrome 会调用 Pdf 控制器两次:

开发者工具显示第二个请求被取消。

在控制器中创建 PDF 需要花费大量时间。 如何强制浏览器仅发送单个请求? 或者在这种情况下如何在控制器中检测虚假请求而不生成pdf?

更新

页面定义为

<!DOCTYPE html>

<html>
<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <link href="/css/redmond/jquery-ui.css" rel="stylesheet" />
    <link href="/Content/font-awesome.min.css" rel="stylesheet" />
    <link href="/Content/bootstrap.css" rel="stylesheet" />
    <link href="/Content/bootstrap-theme.css" rel="stylesheet" />
    <link href="/Scripts/jqgrid-4.9.1/css/ui.jqgrid.css" rel="stylesheet" />
    <link href="/Content/Css/Site.css" rel="stylesheet" />
    <script src="/Scripts/jquery-1.12.4.js"></script>
    <script src="/Scripts/jquery-ui-1.11.4.js"></script>
    <script src="/Scripts/i18n/jquery.ui.datepicker-et.js"></script>
    <script src="/Scripts/bootstrap.js"></script>
    <script src="/Scripts/jqgrid-4.9.1/js/i18n/grid.locale-et.js"></script>
    <script src="/Scripts/jqgrid-4.9.1/js/jquery.jqgrid.src.js"></script>
    <script src="/Scripts/jqgrid-4.9.1/plugins/jquery.jqgrid.showhidecolumnmenu.js"></script>
    <script src="/Scripts/jqgrid-4.9.1/plugins/jquery.contextmenu-ui.js"></script>
    <script src="/Scripts/jqgrid-4.9.1/plugins/jquery.createcontexmenufromnavigatorbuttons.js"></script>
    <script src="/Scripts/json2.js"></script>
    <script src="/Scripts/jquery.form.js"></script>
    <script src="/Scripts/myerp.js"></script>
    <script src="/Scripts/TinyMCE/tiny_mce.js"></script>
    <script src="/Scripts/TinyMCE/jquery.tinymce.js"></script>
   ...
</head>
<body>
   ...
    <div class="container-fluid">
        <form id="_form" target="_blank" class='form-inline'>
            <div class="panel panel-warning">
                <div id='contentCaptionDiv' class="panel-heading">
                        <input type="submit" id='_submit' class="btn btn-primary"
                               formaction='/Report/Html'
                               formtarget="_blank"
                               value='Show html' />

                        <input type="submit"
                               formaction='/Report/Pdf'
                               class="btn btn-info"
                               formtarget="_blank"
                               value='PDF' />
                        <input type="submit"
                               formaction='/Report/Xls'
                               class="btn btn-warning"
                               formtarget="_blank"
                               value='CSV' />
                        <input type="submit"
                               formaction='/Report/Designer?_entity=DokGReport&amp;_dokumnrs=130637'
                               formtarget="_blank"
                               class="btn btn--inverse"
                               value='Change' />
                        ...
                        <script>
                    $(function () {
                        var lastFocus = [];
                        var elements = getFocusableElements();
                        elements.focus(function () {
                            lastFocus = $(this);
                        });
                        $('#_form').keypress(function (e) {
                            if (enter(e)) {
                                $('#_submit').click();
                                return false;
                            }
                        });

                        $('#sendemail').click(function (e) {

                            $('#_form').attr('action', $(this).attr('formaction'))
                                 .attr('target', $(this).attr('formtarget'));
                        });



                        elements.eq(0).focus().select();

                        $('#_Report').dblclick(function () {
                            $('#_submit').click();
                        });


                        $('#_form').on('click', 'input[type=submit]', function (e) {
                            var attr = this.getAttribute('formAction');
                            if (attr) {
                                this.form.action = attr;
                            }
                        });

                    });
                    </script>
                </div>
            </div>
        </form>
    </div>
</body>
</html>

【问题讨论】:

  • 如何调用pdf动作方法?例如,按钮单击或浏览器中的普通 URL。
  • 查看这篇文章:rion.io/2013/02/24/…
  • @Win 我更新了问题并添加了用于 Pdf 呼叫控制器的代码
  • 您能否发布导致回发的整个表单标签和脚本?

标签: asp.net asp.net-mvc google-chrome asp.net-mvc-4 pdf


【解决方案1】:

您不能也不应该尝试这样做。用户可以随意点击刷新按钮。您应该在您的操作方法中检查文件是否已经创建并返回结果。

public ActionResult Pdf()  {

    byte[] result = GetExistingOrCreatePDF();
    var ms = new MemoryStream(result);
    return new FileStreamResult(ms, "application/pdf");
}
public byte[] GetExistingOrCreatePDF()
{
  //Check whether the PDF is already generated and exist in a DISK location. 
  // If yes, read it and return the byte array
  // else , create , store and return.
}

【讨论】:

  • 用户单击刷新按钮一次,但 Chrome 发送两个请求。 pdf 是在内存中创建的,而不是在磁盘中。 Pdfs 是文档,是从数据库数据动态创建的。如何防止或忽略重复的 Chrome 请求?可能可以使用过期时间较短的 MemoryCache,但不需要为重复请求发送 pdf,因此应该丢弃重复请求
  • 所以你需要检查你的刷新按钮代码,看看为什么它会发送 2 个请求!
  • 浏览器刷新时也会出现这种情况:PDF 显示在浏览器选项卡中。如果 pdf 选项卡处于活动状态,则按下浏览器刷新按钮。按下浏览器刷新按钮 Chrome 发送两个请求后,pdf 选项卡中没有用户代码,浏览器在那里呈现 pdf。
猜你喜欢
  • 2011-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-14
  • 1970-01-01
  • 2012-08-26
  • 2015-03-09
  • 1970-01-01
相关资源
最近更新 更多