在调用控制器

时间:2018-03-30 15:45:23

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

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

<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");
}

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

1 个答案:

答案 0 :(得分:1)

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

  

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

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

  1. 将文件保存到存储,然后为用户提供生成的链接
  2. <强>的Ajax

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

    控制器(服务器端)

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

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

    1. 动态创建文件
    2. <强> HTML

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

      控制器(服务器端)

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

      pdf选择:

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

      1。替换活动选项卡

      • 基本HTML:<a href="url">description</a>
      • Javascript / jquery window.open(url, '_self');第二个参数必须是_self_parent
      • 要求:内容处置不是附件

      2。打开新标签

      • 基本HTML:<a href="url" target="_blank">description</a>取决于用户偏好设置
      • 没有第三个参数的Javascript / jquery window.open(url, '_blank');
      • 要求:内容处置不是附件

      3。打开新窗口

      • 基本HTML:<a href="url" target="_blank">description</a>取决于用户偏好设置
      • 带有第三个参数的Javascript / jquery window.open(url, '_blank', 'width=200');
      • 要求:内容处置不是附件

      4。嵌入

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

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

      • 基本HTML:`
      • Javascript / jquery:document.location = url;
      • 要求:内容处置必须是附件

      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 (仅提供网址路径)

      <?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 =&gt;给附件标题

      else =&gt;给内联标题

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

      结论:

      1. 创建脚本,即动态生成pdf而不是真实/直接的pdf路径
      2. 设置标题内容 - 处置:附件与否,每个都有不同的行为
      3. 奖励示例:尝试运行此代码

        <强>的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>