zoukankan      html  css  js  c++  java
  • Download link in response body does not work--待解决

    I am having a problem similar to the ones described in #374 and #1196. I have a service which returns a pdf file as attachment with Content-Disposition header. This works when I call the endpoint from the browser - file is downloaded. On Swagger UI I get a download link after calling the service with response content type application/pdf, however that link downloads an empty pdf file:

    My swagger.json is generated by Enunciate (version 2.3.0) and the relevant part looks like this:

    "responses": {
      "200": {
        "schema": {
        "description": "",
        "$ref": "#/definitions/json_File"
      }, ...
    

    I tried adding "type": "file" to the schema, but it didn't fix the problem. What could be going wrong here?

    https://github.com/swagger-api/swagger-ui/issues/2132

    else if (headers['Content-Disposition'] && (/attachment/).test(headers['Content-Disposition']) ||
            headers['content-disposition'] && (/attachment/).test(headers['content-disposition']) ||
            headers['Content-Description'] && (/File Transfer/).test(headers['Content-Description']) ||
            headers['content-description'] && (/File Transfer/).test(headers['content-description'])) {
           if ('Blob' in window) {
            var type = contentType || 'text/html';
            blob = new Blob([content], {type: type});
             var a = document.createElement('a');
            var href = window.URL.createObjectURL(blob);
            var fileName = response.url.substr(response.url.lastIndexOf('/') + 1);
            var download = [type, fileName, href].join(':');
             // Use filename from response header
            var disposition = headers['content-disposition'] || headers['Content-Disposition'];
            if(typeof disposition !== 'undefined') {
              var responseFilename = /filename=([^;]*);?/.exec(disposition);
              if(responseFilename !== null && responseFilename.length > 1) {
                download = responseFilename[1];
              }
            }
             a.setAttribute('href', href);
            a.setAttribute('download', download);
            a.innerText = 'Download ' + fileName;
             pre = $('<div/>').append(a);
          } else {
            pre = $('<pre class="json" />').append('Download headers detected but your browser does not support downloading binary via XHR (Blob).');
          }

    https://github.com/swagger-api/swagger-ui/commit/4bdaeba797224bde922f3cefe55a6807428437a8

    src="blob:http://" 这种链接格式是怎么做的

    创建一个指向类型数组的URL,具体是做什么的我也看不太懂,官方api给你


    blob的API:https://developer.mozilla.org/zh-CN/docs/Web/API/Blob

    Blob 对象表示一个不可变、原始数据的类文件对象。Blob 表示的不一定是JavaScript原生格式的数据。File 接口基于Blob,继承了 blob 的功能并将其扩展使其支持用户系统上的文件。

    要从其他非blob对象和数据构造一个Blob,请使用 Blob() 构造函数。要创建包含另一个blob数据的子集blob,请使用 slice()方法。要获取用户文件系统上的文件对应的Blob对象,请参阅 File文档。

    接受Blob对象的API也被列在 File 文档中。

    注意:slice()方法原本接受length作为第二个参数,以表示复制到新Blob对象的字节数。如果设置的参数使start + length超出了源Blob对象的大小,那返回的则是从start到结尾的数据。
    注意:slice() 方法在某些浏览器和版本上带有浏览器引擎前缀:比如 Firefox 12及更早版本的blob.mozSlice() 和Safari中的blob.webkitSlice()。 没有浏览器引擎前缀的老版本slice()方法有不同的语义,并且已过时。 Firefox 30 中取消了对blob.mozSlice()的支持。

    https://developer.mozilla.org/zh-CN/docs/Web/API/Blob

    How to download a file in Swagger UI instead of displaying blob of text

    If I enter the URL (http://localhost:13225/hellozip) in a browser the file is download in the usual way.

    However if I navigate to the swagger ui and "Try it now" the response is a blob of text instead of downloading the file. Can you point out what I'm doing incorrectly. Thanks

    [Route("/hellozip")]
    public class HelloZip { }
    
    public object Get(HelloZip request)
    {
        string tempPath = Path.GetTempPath();
        string filePath = Path.Combine(tempPath, "HelloTest.zip");
        base.Response.ContentType = "application/zip";
    
        using (MemoryStream memoryStream = new MemoryStream())
        {
            using (var zipArchive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
            {
                ZipArchiveEntry zipArchiveEntry = zipArchive.CreateEntry("Foo.txt");
                using (Stream stream = zipArchiveEntry.Open())
                {
                    using (StreamWriter streamWriter = new StreamWriter(stream))
                    {
                        streamWriter.Write("Bar!");
                    }
                }
            }
    
            using (var fileStream = new FileStream(filePath, FileMode.Create))
            {
                memoryStream.Seek(0, SeekOrigin.Begin);
                memoryStream.CopyTo(fileStream);
            }
        }
    
        return new HttpResult(new FileInfo(filePath), true);
    }

    使用JavaScript把页面上的表格导出为Excel文件--使用了blob

    如果在页面上展示了一个数据表格,而用户想把这个表格导出为Excel文件,那么在要求不高的情况下,可以不通过服务器生成表格,而是直接利用JavaScript的Blob和Object URL特性将表格导出。不过,丑话说在前头,这篇随笔中利用了Excel能打开HTML文档的特性,所以导出的表格实际上是一个HTML文档,并且其扩展名只能为.xls,而不能是.xlsx,否则Excel无法打开。(不过确实见过使用JavaScript生成真正Excel文件的方案,这里暂不提及。)

    实现代码如下,包含HTML页面和JavaScript脚本:

    <!DOCTYPE html>
    <html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title></title>
        <meta charset="utf-8" />
        <style>
            /* 此样式仅用于浏览器页面效果,Excel不会分离表格边框,不需要此样式 */
            table {
                border-collapse: collapse;
            }
        </style>
    </head>
    <body>
        <!-- 设置border="1"以显示表格框线 -->
        <table border="1">
            <!-- caption元素可以生成表标题,其单元格列跨度为表格的列数 -->
            <caption>学生成绩表</caption>
            <tr>
                <!-- 可以使用rowspan和colspan来合并单元格 -->
                <th rowspan="2">编号</th>
                <th rowspan="2">学号</th>
                <th rowspan="2">姓名</th>
                <th rowspan="2">性别</th>
                <th rowspan="2">年龄</th>
                <th colspan="3">成绩</th>
            </tr>
            <tr>
                <th>语文</th>
                <th>数学</th>
                <th>英语</th>
            </tr>
            <tr>
                <td>1</td>
                <td>2016001</td>
                <td>张三</td>
                <td>男</td>
                <td>13</td>
                <td>85</td>
                <td>94</td>
                <td>77</td>
            </tr>
            <tr>
                <td>2</td>
                <td>2016002</td>
                <td>李四</td>
                <td>女</td>
                <td>12</td>
                <td>96</td>
                <td>84</td>
                <td>89</td>
            </tr>
        </table>
    
        <a>导出表格</a>
    
        <script>
            // 使用outerHTML属性获取整个table元素的HTML代码(包括<table>标签),然后包装成一个完整的HTML文档,设置charset为urf-8以防止中文乱码
            var html = "<html><head><meta charset='utf-8' /></head><body>" + document.getElementsByTagName("table")[0].outerHTML + "</body></html>";
            // 实例化一个Blob对象,其构造函数的第一个参数是包含文件内容的数组,第二个参数是包含文件类型属性的对象
            var blob = new Blob([html], { type: "application/vnd.ms-excel" });
            var a = document.getElementsByTagName("a")[0];
            // 利用URL.createObjectURL()方法为a元素生成blob URL
            a.href = URL.createObjectURL(blob);
            // 设置文件名
            a.download = "学生成绩表.xls";
        </script>
    </body>
    </html>

    效果如图:

    打开下载的文件:

    使用开发者工具检查a元素,就能大致明白blob URL的工作原理:

    <a href="blob:http://localhost:52347/0ead79dc-1896-4a53-b1f1-dfbafff4e953" download="学生成绩表.xls">导出表格</a>

    如果想通过按钮导出文件,可以在按钮的点击事件中创建a元素,配置其属性并触发其点击事件。不过在FireFox中,需要先将创建的a元素放入body中,否则无法下载。

    https://www.cnblogs.com/zhuxinghan/p/6063193.html
    启用编辑之后才会显示图片:

    由于图片是链接,首先确保图片能被 excel 访问。
    这个方法不完美,如果可以用更好的方法,还是不要用这个了。

    <html>
      
     <head>
      
     <title>123</title>
      
     <SCRIPT LANGUAGE="javascript"><script>
         var idTmr = "";
         function copy(tabid) {
             var oControlRange = document.body.createControlRange();
             oControlRange.add(tabid, 0);
             oControlRange.select();
             document.execCommand("Copy");
         }
         function toExcel(tabid) {
             copy(tabid);
             try {
                 var xls = new ActiveXObject("Excel.Application");
             } catch (e) {
                 alert("Excel没有安装或浏览器设置不正确.请启用所有Active控件和插件");
                 return false;
             }
             xls.visible = true;
             var xlBook = xls.Workbooks.Add;
             var xlsheet = xlBook.Worksheets(1);
             xlBook.Worksheets(1).Activate;
             for (var i = 0; i < tabid.rows(0).cells.length; i++) {
                 xlsheet.Columns(i + 1).ColumnWidth = 15;
             }
             xlsheet.Paste;
             xls = null;
             idTmr = window.setInterval("Cleanup();", 1);
         }
         function Cleanup() {
             window.clearInterval(idTmr);
             CollectGarbage();
         }
    </script>
     </head>
      
      
      
     <body>
         <input type="button" value="导入excel" onclick="toExcel(tt)">
    <table border="1" id="tt" cellspacing="1">
                                                    <thead>
                                                        <tr>
                                                            <th colspan='7'> 基本信息 </th>
                                                        </tr>
                                                        <tr>
                                                            <th>编号</th>
                                                            <th class="strStaffCode">4564588</th>
                                                            <th>姓名</th>
                                                            <th class="strStaffName">张三</th>
                                                            <th>性别</th>
                                                            <th class="strSex"></th>
                                                            <th rowspan='2'>
                                                                <img src="assets/img/picture-2.jpg" width="100" height="200" alt=""/>
                                                            </th>
                                                        </tr>
                                                        <tr>
                                                            <th>出生年月</th>
                                                            <th class="strBirthday">1994-03</th>
                                                            <th>籍贯</th>
                                                            <th class=" strNativePlace">辽宁</th>
                                                            <th>民族</th>
                                                            <th class="strNation">汉族</th>
                                                        </tr>
                                                </thead>
    </table>
     </body>
      
     </html>
    这个适用ie,能导出excel+其中的图片,防止大伙迷路,直接粘上来

    https://www.cnblogs.com/zhuxinghan/p/6063193.html
    关于Blob 前端下载文件(例如excel)功能(主要用于vue 或者 ajax 前端下载)

    公司前端使用的是vue,现在需要导出excel,在网上查了一些资料,推荐用Blob
    - 首先介绍一下Blob
    一直以来,JS都没有比较好的可以直接处理二进制的方法。而Blob的存在,允许我们可以通过JS直接操作二进制数据。
    一个Blob对象就是一个包含有只读原始数据的类文件对象。Blob对象中的数据并不一定得是JavaScript中的原生形式。File接口基于Blob,继承了Blob的功能,并且扩展支持了用户计算机上的本地文件。
    Blob对象可以看做是存放二进制数据的容器,此外还可以通过Blob设置二进制数据的MIME类型。

    之前以为Blob需要二进制文件流,在后台返回的时候返回二进制,发现下载下来的内容不对,后来查了一下 java是可以直接返回Blob对象的

    前端使用axios发送请求

    this.axios({
            method:'get',
            url:url,//后台请求地址
            responseType:'blob',
          }).then((data) => {
            if (!data) {
                return
            }
            let url = window.URL.createObjectURL(data.data)
            let link = document.createElement('a')
            link.style.display = 'none'
            link.href = url
            link.setAttribute('download', 'product.xls')
            document.body.appendChild(link)
            link.click()
          })

    这里重点是responseType:’blob’,加上这个之后后台就会返回Blob对象

    后台代码 (java)

    public DownloadResult exportXls(ActionContext ac){
    
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    
            ActionResult ar = new ActionResult();
            JSONObject args = ac.getArguments();
            String entityId = JsonUtil.getString(args, "entityId");
            String date = JsonUtil.getString(args, "date");
            DownloadResult localDownloadResult = new DownloadResult();
            HttpServletResponse response = ac.getResponse();
    
            String getDataSql = "select FProduct_name,FCustom_contact_name,FOrder_amount,FDeparture_date,FCreateTime,FPeopleNum from lpp_Order_table where FCreateTime >= '" + date + " 00:00:00' and FCreateTime <= '" + date + " 23:59:59' and FProductId = ? ";
    
            List<Record> dataRes = Executor.getInstance("default").getRecordList(getDataSql, entityId);
    
            ByteArrayOutputStream out = new ByteArrayOutputStream();
    //        OutputStream out = null;
            try {
                    Workbook wb = new HSSFWorkbook();
                    //省略生成excel的代码
                    wb.write(out);
    
                byte[] array = out.toByteArray();
                ar.putClientValue("data", array);
                localDownloadResult.setFileName("total.xls");
                localDownloadResult.setContent(array);
            } catch(Exception ex) {
                ex.printStackTrace();
            } finally {
            }
    
            return localDownloadResult;
        }
    }

    DownloadResult 是我们公司平台封装的一个下载用的类,其实就是response在响应,返回值需要时二进制byte[]数组,这样之后前端就可以下载到excel


    ---------------------
    作者:纯白mi
    来源:CSDN
    原文:https://blog.csdn.net/u010736165/article/details/80744628
    版权声明:本文为博主原创文章,转载请附上博文链接!
    Vue操作blob相关的文章
    https://blog.csdn.net/bjLiuqaq/article/details/81282581
    https://blog.csdn.net/Shimeng_1989/article/details/81773868?utm_source=blogxgwz0

    https://blog.csdn.net/hefeng6500/article/details/82988624

    通过blob(用来存储二进制大文件)包装ajax(或axios)请求到的data数据,实现下载EXCEL(或其他如图片等)文件

    //案例一
    axios:设置返回数据格式为blob或者arraybuffer
    如:
        var instance = axios.create({         ... //一些配置
            responseType: 'blob', //返回数据的格式,可选值为arraybuffer,blob,document,json,text,stream,默认值为json
        })
    请求时的处理:
      getExcel().then(res => {
          //这里res.data是返回的blob对象    
          var blob = new Blob([res.data], {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8'}); //application/vnd.openxmlformats-officedocument.spreadsheetml.sheet这里表示xlsx类型
          var downloadElement = document.createElement('a');
          var href = window.URL.createObjectURL(blob); //创建下载的链接
          downloadElement.href = href;
          downloadElement.download = 'xxx.xlsx'; //下载后文件名
          document.body.appendChild(downloadElement);
          downloadElement.click(); //点击下载
          document.body.removeChild(downloadElement); //下载完成移除元素
          window.URL.revokeObjectURL(href); //释放掉blob对象
     })
    //案例二
     
    function createDownload(fileName, content){
        var blob = new Blob([content]);
        var link = document.createElement("a");
        link.innerHTML = fileName;
        link.download = fileName;
        link.href = URL.createObjectURL(blob);
        document.getElementsByTagName("body")[0].appendChild(link);
    }
    createDownload("download.txt","download file");
    //案例三<br>
    function downloadExport(data) {
      return axios.post(url, data).then((res)=>{
        const content = res
        const blob = new Blob(["uFEFF" + content.data],{ type: "application/vnd.ms-excel;charset=utf-8"})
        const fileName = '卡密.xls'
        if ('download' in document.createElement('a')) { // 非IE下载
          const elink = document.createElement('a')
          elink.download = fileName
          elink.style.display = 'none'
          elink.href = URL.createObjectURL(blob)
          document.body.appendChild(elink)
          elink.click()
          URL.revokeObjectURL(elink.href) // 释放URL 对象
          document.body.removeChild(elink)
        } else { // IE10+下载
          navigator.msSaveBlob(blob, fileName)
        }
      });
    }

    https://www.cnblogs.com/xuanbingbingo/p/8621755.html


    http://blog.csdn.net/leonzhouwei/article/details/8447643

    原因是 Excel 以 ANSI 格式打开,不会做编码识别。

    解决方法:

    function downloadCSV(fileName, content) {
        let a = document.createElement('a');
        let file = URL.createObjectURL((new Blob(['uFEFF' + content], { type: 'text/csv;charset=utf-8' })));
    
        a.href = file;
        a.download = `${fileName}.csv`;
        a.click();
    }

           http://stackoverflow.com/questions/19492846/javascript-to-csv-export-encoding-issue

    https://github.com/lishengzxc/bblog/issues/30

  • 相关阅读:
    页面跳转
    获取gridview 某列的值
    C#日期格式化的几种处理方法(转)
    asp.net 退出 按钮
    asp.net控件大全(一)
    导出Excel
    DropDownList的二级联动 (SqlDataSource实现和SQL 绑定实现)
    asp.net控件大全(二)
    如何让Gridview在没有数据的时候显示表头(asp.net)
    自定义日期格式
  • 原文地址:https://www.cnblogs.com/softidea/p/9835135.html
Copyright © 2011-2022 走看看