一、ajax请求获取二进制流文件(blog)解决办法

本文详细介绍了使用Ajax请求获取二进制流文件的解决方案,包括前端如何通过Blob处理响应,以及后端PHP生成并输出Excel文件的过程。特别关注了如何从前端下载由后端生成的二进制文件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、ajax请求获取二进制流文件解决办法

今天在做excel导出的时候,碰到了一系列问题,以下是记录。

首先,整个过程就是现在前台页面先封装好要下载的文件数据,然后点击按钮触发了ajax请求,然后后台php就进行了数据的获取,处理数据,然后引用php的插件Spreadsheet生成了对应的图表,然后直接对着前台输出了:

以下为后台php代码向前端输出的文件流
header(‘filename:’.$file_name);
//没有缓存
header(‘Cache-Control:no-cache,no-store’);
//允许获取的访问头部
header(‘Access-Control-Expose-Headers:filename’);
w r i t e r = I O F a c t o r y : : c r e a t e W r i t e r ( writer = IOFactory::createWriter( writer=IOFactory::createWriter(spreadsheet, ‘Xlsx’);
$writer->save(‘php://output’);

以上就是tp5后端控制器方法的结束,那么问题来了

以上返回的报文中,所储存的是二进制流文件。然后用惯了jq的ajax的我,就懵逼了,一直以为数据交流只有html,text,json,xml,然后查了资料后发现原来还有blob这种数据交流。

然后就用了纯js去获取数据,然后得到数据后
以下是整个前端获取数据流并下载的流程(重点)

var url=server_url+'/index/index/get_rep';   //请求的URl
            var xhr = new XMLHttpRequest();		//定义http请求对象
            xhr.open("POST", url, true);		
            xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
            xhr.send("userId="+username+"&password="+password+"&repo_type="+type+"&repo_time=");
            xhr.responseType = "blob";  // 返回类型blob
            xhr.onload = function() {   // 定义请求完成的处理函数,请求前也可以增加加载框/禁用下载按钮逻辑
                if (this.status===200) {
                    var blob = this.response;
                    var reader = new FileReader();
                    reader.readAsDataURL(blob);  // 转换为base64,可以直接放入a表情href
                    reader.onload=function (e) {
                        console.log(e);			//查看有没有接收到数据流
                        // 转换完成,创建一个a标签用于下载
                        var a = document.createElement('a');
						a.download="data_repo"+".xlsx";			//自定义下载文件名称
                        a.href = e.target.result;
                        $("body").append(a);    // 修复firefox中无法触发click
                        a.click();
                        $(a).remove();
                    }
                }
                else{
                    alert("出现了未知的错误!");
                }
            }

上面就是整个前后台blob数据流文件交流, (下面为片段解释) :

var reader = new FileReader();
reader.readAsDataURL(blob); 

这种方式读取文件完之后,又使用了

reader.onload=function (e) {
                        console.log(e);
                        // 转换完成,创建一个a标签用于下载
                        var a = document.createElement('a');
						a.download="data_repo"+".xlsx";			//自定义下载文件名称
                        a.href = e.target.result;
                        $("body").append(a);    // 修复firefox中无法触发click
                        a.click();
                        $(a).remove();
                    }

这种方式来下载读取完的目标文件,然后用a链接下载下来


分割线

分享个vue学习的教程

本人亲自维护的接口

非常适合vue零基础或者刚入门vue的小白学习。

资源包括源码、视频、接口文档,从入门到实战项目

如果你想学习vue,这里有个项目线上尝鲜地址:http://129.226.76.172:5325


在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述在这里插入图片描述

<think>好的,我现在需要帮助用户解决如何处理和下载二进制文件流的问题。用户提到他们找到了两种方法,种是返回HTTP地址,另种是处理二进制流,他们现在想了解如何处理二进制文件流的教程、示例和代码。 首先,我需要回忆下前端处理二进制流的方法。通常,后端返回二进制流时,前端需要通过Ajax请求获取数据,然后将其转换为Blob对象,再创建URL对象,最后触发下载。这个过程可能涉及到设置正确的响应类型,比如`responseType: 'blob'`,这样浏览器才能正确解析二进制数据。 接下来,我需要考虑用户可能的疑问点。例如,如何确保请求正确获取二进制流?如何处理可能的错误?跨域问题怎么解决?还有如何设置文件名?这些都需要在回答中覆盖。 然后,我应该组织步骤,分点说明,让用户能步步跟随。首先,前端发送请求,设置responseType为'blob',然后处理响应,将数据转为Blob,创建临时URL,使用a标签触发下载,最后释放URL资源。同时,要提到如何从响应头获取文件名,或者如何自定义文件名。 代码示例很重要,用户可能需要个完整的示例来参考。需要提供个使用Fetch API和XMLHttpRequest两种方法的例子,因为有的项目可能还在用旧的方法。同时,要指出不同方法的优缺点,比如Fetch更现代,但可能需要兼容处理。 另外,需要注意的细节,比如Blob的类型是否正确,比如对于Excel文件是`application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`,而PDF是`application/pdf`。如果后端没有正确设置Content-Type,前端可能需要手动指定。 还要提到可能的错误处理,比如网络错误或后端返回的不是文件流的情况,如何捕获并提示用户。例如,检查响应状态码,或者检查Blob的大小是否为0。 关于引用,用户提供的引用[1]和[2]已经提到两种方式,所以需要在回答中引用这些内容,特别是在讨论两种方法优劣的时候,比如节省服务器资源,但前端处理稍复杂。 最后,生成相关问题,帮助用户进步了解相关内容,比如不同MIME类型、动态设置文件名、错误处理、跨域问题,以及与大文件下载相关的技术如分片下载或断点续传。 总结步骤: 1. 前端请求设置responseType为blob 2. 接收响应并转换为Blob 3. 创建对象URL 4. 创建a标签触发下载 5. 清理资源 6. 文件名处理 7. 错误处理 8. 提供代码示例(Fetch和XHR) 9. 注意事项(MIME类型、兼容性) 10. 相关问题生成 需要确保所有技术细节准确,比如Blob的使用和URL.revokeObjectURL的重要性,避免内存泄漏。同时,语言要简洁明了,适合不同水平的开发者理解。</think>### 如何处理和下载二进制文件流 以下是前端处理二进制文件流并实现下载的详细步骤和示例代码: --- #### **1. 发送请求获取二进制流** 前端需通过 `XMLHttpRequest` 或 `Fetch API` 发起请求,并设置响应类型为 `blob`,告知浏览器返回二进制数据流。 ```javascript // 使用 Fetch API fetch('/api/download', { method: 'GET', headers: { 'Content-Type': 'application/octet-stream' } }) .then(response => response.blob()) .then(blob => { handleDownload(blob, 'filename.pdf'); }); // 使用 XMLHttpRequest const xhr = new XMLHttpRequest(); xhr.open('GET', '/api/download', true); xhr.responseType = 'blob'; xhr.onload = function() { if (this.status === 200) { const blob = new Blob([this.response]); handleDownload(blob, 'filename.pdf'); } }; xhr.send(); ``` --- #### **2. 转换二进制流并触发下载** 将二进制流转换为 `Blob` 对象,生成临时 URL,通过动态创建 `<a>` 标签模拟点击下载。 ```javascript function handleDownload(blob, filename) { // 创建临时 URL const url = window.URL.createObjectURL(blob); // 动态创建 <a> 标签触发下载 const a = document.createElement('a'); a.href = url; a.download = filename; // 设置文件名 a.click(); // 释放 URL 资源 window.URL.revokeObjectURL(url); } ``` --- #### **3. 文件名处理** - **从响应头获取文件名**:后端需在响应头中设置 `Content-Disposition`,例如: ```http Content-Disposition: attachment; filename="report.pdf" ``` 前端解析方式: ```javascript const contentDisposition = response.headers.get('Content-Disposition'); const filename = contentDisposition.split('filename=')[1].replace(/"/g, ''); ``` - **自定义文件名**:若后端返回文件名,可手动指定 `a.download = '自定义文件名.xlsx'`。 --- #### **4. 错误处理** 捕获请求异常并处理无效响应: ```javascript fetch('/api/download') .then(response => { if (!response.ok) throw new Error('下载失败'); return response.blob(); }) .then(blob => { if (blob.size === 0) throw new Error('文件为空'); handleDownload(blob, 'file.pdf'); }) .catch(error => { console.error('Error:', error); alert('下载失败,请重试'); }); ``` --- #### **5. 注意事项** - **MIME 类型匹配**:根据文件类型设置正确的 `Blob` 类型,例如: - Excel: `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet` - PDF: `application/pdf` ```javascript const blob = new Blob([data], { type: 'application/pdf' }); ``` - **跨域问题**:确保后端配置 CORS 允许文件下载。 - **大文件下载**:可显示进度条(通过 `xhr.onprogress` 事件)或分片下载。 --- ### 示例代码(整合版) ```html <button onclick="downloadFile()">下载文件</button> <script> function downloadFile() { fetch('/api/download', { responseType: 'blob' }) .then(response => { const filename = extractFilename(response.headers); return response.blob().then(blob => ({ blob, filename })); }) .then(({ blob, filename }) => { const url = window.URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = filename; a.click(); window.URL.revokeObjectURL(url); }) .catch(error => alert(`下载失败: ${error.message}`)); } function extractFilename(headers) { const disposition = headers.get('Content-Disposition'); return disposition ? disposition.split('filename=')[1].replace(/"/g, '') : 'default.txt'; } </script> ``` --- ### 关键引用说明 - 接口返回二进制流可节省服务器存储资源,但需前端解析[^1]。 - 二进制流下载需通过 `Blob` 和对象 URL 实现,而非直接使用 `window.open`[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值