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>
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
Download link in response body does not work--待解决的更多相关文章
- Microsoft Visual Studio 2013 Update 5 direct download link for full ISO
		
From:http://www.nickdu.com/?p=604 Visual Studio 2013 Update 5 is now released and maybe you are also ...
 - Toad for Oracle 12 download link
		
Toad for Oracle 12 download link x64-bit http://us-downloads.quest.com/Repository/support.quest.com/ ...
 - 一個不錯的免費流程圖制作軟件  Download link
		
The process flow software you saw yesterday which is a free software, but you need to register. Down ...
 - vsftpd出现“Response: 500 OOPS: cannot change directory”解决方法(转载)
		
vsftpd出现“Response: 500 OOPS: cannot change directory”解决方法 笔者用的Linux发行版本为centos当用FTP客户端连接时,出现如下错误提示 ...
 - 转(Response.WriteFile 无法下载大文件解决方法)
		
以前用Response.WriteFile(filename),但当遇到大文件时无法完整下载. 该方法最大的问题,它不是直接将数据抛到客户端,而是在服务器端(IIS)上缓存.当下载文件比较大时,服务器 ...
 - 创建link server链接服务器碰到的问题及解决办法
		
问题描述 今天在做数据库迁移,然后新建link server(链接服务器)的时候,碰到以下问题. 我的sql 脚本是这样的. 然后,执行的时候就收到以下错误信息. Msg 468, Level 16, ...
 - grails中报Cannot create a session after the response has been committed异常的解决办法
		
在grails中,我们在layouts\main.gsp中使用类似如下的代码来判断当前用户处于登录状态时显示相关的登录信息: <g:if test="${session.users}& ...
 - postman6 在Linux中,body和response字体显示不正常的解决方法
		
在Linux中,postman的body和response使用的默认字体如果没有安装的话,会导致字体和光标的位置不一致,例如字体显示长度只有30,而光标在70的位置,导致编辑困难. 经查找css的定义 ...
 - ASP: Response 对象 错误 'ASP 0251 : 80004005' 解决办法
		
Response 对象 错误 'ASP 0251 : 80004005' 超过响应缓冲区限制 这种情况一般是因为需要输出的网页内容太大了,由于asp在输入内容到客户的浏览器上之前,会把需要输出的全部内 ...
 
随机推荐
- uwsgi启动提示:probably another instance of uWSGI is running on the same address (:8002). bind(): Address already in use [core/socket.c line 769]
			
提示8002端口被占用,可以这样终止掉后再启动 sudo fuser -k 8002/tcp
 - “全栈2019”Java第三十八章:类与方法
			
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
 - sonar阻断级别错误(block)简单汇总
			
1.代码里面包含PASSWORD.PWD 'PWD' detected in this expression, review this potentially hardcoded credential ...
 - PHP中implode()和explode()
			
1, implode()函数返回由数组元素组合成的字符串,函数语法:string implode(separator,array),separator参数可选,规定数组元素之间放置的内容,默认是空字符 ...
 - [译文]casperjs使用说明-测试
			
capserjs自带了一个测试框架,它提供了一个使你能够更容易的测试你的web应用的工具集. 注意: 1.1版本变更 这个测试框架,包括它的所有API,仅能使用在casperjs test子命令下 如 ...
 - postgres常用命令
			
1.登录 psql -U pname -d database // pname 表示postgres的登录用户名,database 则表示要访问的数据库 2.查看所有的数据库 \l 3.查看所有的表 ...
 - NASA的10条代码编写原则
			
NASA的10条代码编写原则 作者: Gerard J. Holzmann 来源: InfoQ 原文链接 英文原文:NASA's 10 Coding Rules for Writing Safety ...
 - python脚本中appium的自启动自关闭
			
前提:已安装appium命令行版本 将appium的启动及其关闭直接写在脚本中,运行起来会方便很多 创建startAppiumServer.bat 和 stopAppiumServer.bat文件,然 ...
 - python全栈开发_day7_字符编码,以及文件的基本读取
			
一:字符编码 1)什么是字符编码 将人能识别的字符等高级标识符与计算机所能识别的二进制01进行转化,这之间的交流需要一个媒介,进行两种标识符之间的转化. 字节的存储方式为八个二进制位 2)乱码 存放数 ...
 - 2018牛客多校6 - I Team Rocket KD树维护空间
			
题意:给出n条铁路区间\([L,R]\),共有m个boom依时间顺序放置在\(k_i\)中,区间与\(k_i\)有交集的都被炸掉 求每次炸掉的铁路个数和最后输出所有id被炸的时间点 炸弹能炸到的区间满 ...