【问题标题】:Return PDF file to user after ajax call to controllerajax 调用控制器后将 PDF 文件返回给用户
【发布时间】:2018-03-30 15:45:22
【问题描述】:

我的 Kendo Grid 上有一个自定义按钮“导出为 PDF”。单击此按钮后,我会调用生成 PDF 文件的服务。我希望能够在单击“导出为 PDF”按钮时显示此 PDF 文件。我让它工作到它调用服务的地步,我现在将PDF本地保存在我的机器上。如何将此文件返回到视图,以便它显示在新选项卡上,或者可能只是一个要求用户打开并保存保存的对话框。 以下是调用控制器的按钮点击方法:

<script>
    function ExportDocGen_Click() {
        var grid = $("#companyMasterRateSheets").data("kendoGrid");
        var selectedItem = grid.dataItem(grid.select());
        var orderQuoteId = selectedItem.QuoteID;
        $.ajax({
            url: '@Url.Action("GenerateRateSheetPDF", "AccountDetail")',
            type: 'GET',
            dataType: 'string',
            cache: false,
            data: { 'orderQuoteId': orderQuoteId },
            success: function (color) {
                return color;
            },
            error: function () {
                alert('Error occured');
            }
        })
    }
</script>

控制器如下:

[HttpGet]
        public string GenerateRateSheetPDF(string orderQuoteId)
        {
byte[] pdfData = ServiceManager.BuildPDF(Convert.ToInt32(orderQuoteId));
            if (pdfData != null)
            {                   
                BinaryFormatter bf = new BinaryFormatter();
                MemoryStream ms = new MemoryStream();
                bf.Serialize(ms, pdfData);                    
                System.IO.File.WriteAllBytes("hello.pdf", pdfData);
            }          
            return ("hi");
}

我现在正在返回字符串,因为我不确定返回类型应该是什么。感谢您的帮助。

【问题讨论】:

    标签: c# jquery ajax asp.net-mvc pdf


    【解决方案1】:

    因为还没有人回答/评论这个问题。我想我需要帮助你做这件事(所有语言)

    我不知道.netkendo 但我会给你现场演示和简单的解释。我的代码是用 PHP 编写的,但我会尝试一般性地解释这一点,因为这是任何 Web 开发人员的常见问题

    有两种方法可以做到这一点:

    1. 将文件保存到存储中,然后将生成的链接提供给用户

    Ajax

    $.ajax({
      url: '/generatePDF',
      success: function(d){
        document.location = d;
      }
    })
    

    控制器(服务器端)

    var pdf = createPDF();
    saveToServer(pdf, 'path/filename.pdf'); 
    

    这将为用户提供 pdf 真实路径。 (我认为你不想要这个)

    1. 动态创建文件

    HTML

    <a href="url_controller">description</a>
    

    控制器(服务器端)

    var pdf = createPDF();
    addHeader('Content-Disposition: attachment or inline');
    printToScreen(pdf); 
    

    pdf选择:

    • 替换活动标签
    • 打开新标签
    • 打开新窗口
    • 嵌入
    • 强制下载(客户端存储)
    • 本地保存(服务器存储)

    1。替换活动标签

    • 基本 HTML:&lt;a href="url"&gt;description&lt;/a&gt;
    • Javascript /jquery window.open(url, '_self'); 第二个参数必须是 _self_parent
    • 要求:Content-Disposition 不是附件

    2。打开新标签

    • 基本 HTML:&lt;a href="url" target="_blank"&gt;description&lt;/a&gt; 取决于用户偏好设置
    • Javascript /jquery window.open(url, '_blank'); 不带第三个参数
    • 要求:Content-Disposition 不是附件

    3。打开新窗口

    • 基本 HTML:&lt;a href="url" target="_blank"&gt;description&lt;/a&gt; 取决于用户偏好设置
    • Javascript /jquery window.open(url, '_blank', 'width=200'); 带第三个参数
    • 要求:Content-Disposition 不是附件

    4。嵌入

    • 基本 HTML:&lt;embed src="url"&gt;&lt;/embed&gt;
    • javascript/jquery:$(selector).html('&lt;embed src="url"&gt;&lt;/embed&gt;');
    • 要求:无论Content-Disposition是否为附件,浏览器总是尝试显示它

    5。强制下载(客户端存储)

    • 基本 HTML:`
    • Javascript /jquery:document.location = url;
    • 要求:Content-Disposition 必须是附件

    6。本地保存(服务器存储)

    我不会解释这个,因为: - 你已经这样做了 - 每种语言都有不同的语法


    示例实现

    index.html (html + js)

    <!-- 
        basic html: depend on user browser preference setting to open as new window or new tab
    -->
    <a href="http://creativecoder.xyz/stackoverflow/pdf-choice/createpdf.php?file=dummy.pdf" target="_blank"><button id="newtab1">new tab/new window: basic html</button></a> 
    
    <!--
        force to open new tab
        case: without ajax
    -->
    <button id="newtab2">new tab: jquery without ajax</button> 
    
    <!--
        force to open new tab
        case: with ajax
    
        hint:
        * window.open() outside ajax will NOT BLOCKED
        * window.open() inside ajax will BLOCKED
        * so we need to hack this
        * 1st: prepare/declare new var to store blank window
        * 2nd: change location.href to execute it inside ajax
    -->
    <button id="newtab3">new tab: jquery with ajax</button> 
    
    <!--
        force to open new window
        case: without ajax
    -->
    <button id="newwindow1">new window: jquery without ajax</button> 
    
    <!--
        force to open new window
        case: with ajax
    -->
    <button id="newwindow2">new window: jquery with ajax</button> 
    
    <!-- 
        embed
    -->
    <button id="embed">embed</button> 
    
    <!--
        the most easy way
        force download using HTML5 anchor download attribute
        maybe not work for old browser
        hint:
        - no download attribute: display pdf
        - download attribute exists,  but content-disposition header is not set as attachment: display pdf
        - download attribute exists,  but content-disposition header is set as attachment: download pdf
    -->
    <a href="http://creativecoder.xyz/stackoverflow/pdf-choice/createpdf.php?file=dummy.pdf" download="newname.pdf"><button id="forcedownload1">force download using anchor download attribute (fail)</button></a>  
    <a href="http://creativecoder.xyz/stackoverflow/pdf-choice/createpdf.php?file=dummy.pdf&force=1" download="newname.pdf"><button id="forcedownload1">force download using anchor download attribute (correct)</button></a>  
    
    <!--
        force download using ajax
        i think this work in old browser too, since jquery take care of them
    -->
    <button id="forcedownload2">force download 2 using ajax/jquery</button> 
    
    <hr>
    <div id="preview-embed"></div>
    
    <script src="jquery.min.js"></script>
    <script>
    $(function(){
    
        /*
        * you need to read window.open() first: https://www.w3schools.com/jsref/met_win_open.asp to understand the basic
        * hint:
        * window.open() recieve 4 parameter
        * if we not set 3rd parameter: will force open new tab
        * if we set 3rd parameter: will force open new window
        */
    
        $('#newtab2').click(function(){
            /*
            * no matter content-disposition is attachment or not, it always display in browser
            */
            window.open('http://creativecoder.xyz/stackoverflow/pdf-choice/createpdf.php?filename=dummy.pdf');
        });
    
        $('#newtab3').click(function(){
            var newWindow = window.open("","window name");
            $.ajax({
                url: 'http://creativecoder.xyz/stackoverflow/pdf-choice/givemethelink.php',
                success: function(d){
                    newWindow.location.href = d;
                },
                error: function(d){
                    alert('error');
                }
            });
        });
    
        $('#newwindow1').click(function(){
            window.open('http://creativecoder.xyz/stackoverflow/pdf-choice/createpdf.php?filename=dummy.pdf','window name', 'width=200,height=100');
        });
    
        $('#newwindow2').click(function(){
            var newWindow = window.open("","window name", 'width=200,height=100');
            $.ajax({
                url: 'http://creativecoder.xyz/stackoverflow/pdf-choice/givemethelink.php',
                success: function(d){
                    newWindow.location.href = d;
                },
                error: function(d){
                    alert('error');
                }
            });
        });
    
        $('#embed').click(function(){
            $('#preview-embed').html('<embed src="http://creativecoder.xyz/stackoverflow/pdf-choice/createpdf.php?file=dummy.pdf"></embed>');
        });
    
        $('#forcedownload2').click(function(){
            $.ajax({
                /*
                * we need to get file with header attachment
                * if our file is dont have Content-Disposition: attachment , this ajax will display pdf only
                * so we need to set request parameter `force=1` 
                */
                url: 'http://creativecoder.xyz/stackoverflow/pdf-choice/givemethelink.php?force=1', //correct
                //url: 'http://creativecoder.xyz/stackoverflow/pdf-choice/givemethelink.php', //fail
                success: function(d){
                    document.location = d;
                },
                error: function(d){
                    alert('error');
                }
            });
        });
    
    
    });
    </script>
    

    服务器脚本

    服务器脚本示例是用PHP编写的,请使用您自己的语言查找匹配语法。

    这里我将只实现方法 2。我有很多不同的情况。但我会选择我们有 2 个脚本的情况:1. 给出链接 2. 生成 pdf

    givemethelink.php(只给出url路径)

    <?php
    if(isset($_GET['force']) && $_GET['force'] ==1){ //if request GET parameter force exist and the value is 1
        echo 'http://creativecoder.xyz/stackoverflow/pdf-choice/createpdf.php?filename=dummy.pdf&force=1';
    }else{
        echo 'http://creativecoder.xyz/stackoverflow/pdf-choice/createpdf.php?filename=dummy.pdf';
    }
    

    createpdf.php(即时生成 pdf/方法 2)

    <?php
    /*
    * generate pdf on the fly here
    * but here, i only use file_get_contents() to download existing pdf binary
    * and then simply display it to the screen using echo
    * because it can difficult to you to understand, if i give you real php generate pdf script
    */
    
    $source = file_get_contents('dummy.pdf'); //download existing pdf. this line should be pdf generate script
    
    /*
    * set header. this is the key
    * the main header requirement is Content-Disposition
    * you still can set any other header which is optional
    */
    
    header("Content-type: application/pdf"); //tell browser: this is pdf file (optional header example)
    
    /*
    * if is request GET force exists and the value is 1 : force download
    * else display to the browser
    */
    
    if(isset($_GET['force']) && $_GET['force'] ==1){
        header("Content-Disposition: attachment; filename=newname.pdf"); //tell browser: download this
    }else{
        header("Content-Disposition: inline; filename=newname.pdf"); //tell browser: display this file in browser
    }
    
    echo $source; //print pdf source to screen
    

    force=1 => 提供附件标题

    else => 提供内联标题

    这里是现场演示:http://creativecoder.xyz/stackoverflow/pdf-choice/index.html

    结论:

    1. 创建动态生成 pdf 的脚本,而不是真实/直接 pdf 路径
    2. 设置标题内容处置:附件与否,每个都有不同的行为

    额外示例:尝试运行此代码

    test.html

    <a href="http://creativecoder.xyz/stackoverflow/pdf-choice/createpdf.php?filename=dummy.pdf">display 1</a> 
    <a href="http://creativecoder.xyz/stackoverflow/pdf-choice/createpdf.php?filename=dummy.pdf&force=1">download 1</a> 
    <hr>
    <a href="http://creativecoder.xyz/stackoverflow/pdf-choice/createpdf.php?filename=dummy.pdf" target="_blank">display 2</a> 
    <a href="http://creativecoder.xyz/stackoverflow/pdf-choice/createpdf.php?filename=dummy.pdf&force=1" target="_blank">download 2</a> 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-04-02
      • 1970-01-01
      • 2020-08-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-06
      • 1970-01-01
      相关资源
      最近更新 更多