下载文件,浏览器阻止不安全下载

news2025/3/11 15:21:19

背景:

在项目开发中,遇到需要下载文件的情况,文件类型可能是图片、excell表、pdf、zip等文件类型,但浏览器会阻止不安全的下载链接。

效果展示:

下载文件的两种方式: 

一、根据接口的相对url,拼接成完整路径下载

这串完整的下载路径是:

开发预留

在浏览器访问,图片如下:

 结果分析:

直接在浏览器就可以直接访问,可见这个文件没有加密,是不安全的。

 还有一个原因是实际情况,根据接口的url直接下载的。另外一种导出下载,是发起网络请求的,接收后台传给前端的二进制流之前需要先设置responseType为blob,否则默认会以json获取,下载下来的文件打开会提示文件已损坏。是发起网络请求的,并且后端接口返回的response头的content-type也是对应的类型,我的这里是application/vnd.ms-excel;charset=UTF-8。

二、网络接口,导出excell表格 

实现效果:

导出接口: 

这个接口返回的数据在控制台打印:

备注:控制台输出的可以看到是个正确的Blob对象,这就说明我们的配置是对的。 

实现思路【重点】:

导出接口传参给后端,后端对请求到的数据经过后端拼接,然后输出二进制流文件,然后给前端返回,前端直接下载。

需要注意几点:

1.前端请求需要携带请求体,config里面要带上responseType: 'blob'。举例:

    //导出文件【渡船管理】

    exportCrewInfoFile(params) {

        return request.Get("/data/ferryShip/download?", params, {

            headers: {

                "Content-Type": "application/json",

            },

            responseType: 'blob',

        });

    },

所以我们接收后台传给前端的二进制流之前需要先设置responseType为blob,否则默认会以json获取,下载下来的文件打开会提示文件已损坏。

2.后端最好也要配置response头的content-type为对应的类型。

3.需要给这个Blob对象设置一个type,这个type表明改Blob对象所包含数据的MIME类型。如果类型未知,则该值为空字符串。例如:type: "application/vnd.ms-excel",

/**

 *

 * @param {*} res 接口返回的文件流

 */

export const dowloadFileUrl = (res) => {

  console.log(res)

  const fileNames = res.headers['content-disposition']

  if (fileNames) {

      //解码

      const fileName = decodeURIComponent(fileNames.match(/=(.*)$/)[1])

      // 处理返回的文件流

      const content = res.data

      const blob = new Blob([content], {

          // type: res.data.type||"application/vnd.ms-excel",

          type: res.data.type||"application/octet-stream; charset=utf-8"

      });

      if ('download' in document.createElement('a')) {

          //非IE下载

          const a = document.createElement('a') //创建一个a标签

          a.download = fileName //指定文件名称

          a.style.display = 'none' //页面隐藏

          a.href = URL.createObjectURL(blob) // href用于下载地址

          document.body.appendChild(a) //插到页面上

          a.click() //通过点击触发

          URL.revokeObjectURL(a.href) //释放URL 对象

          document.body.removeChild(a) //删掉a标签

      } else {

          //IE10 + 下载

          navigator.msSaveBlob(blob, fileName)

      }

  }

}

三、下载文件的两种方式的对比

实现代码:

代码1:

    if (!data.file) {
      ElMessage.error("文件不存在!");
      return;
    }
    const url = BASEUrl + "/file/" + data.file;//拼接下载地址
    const a = document.createElement("a"); //创建一个a标签
    a.download = data.name; //指定文件名称
    a.style.display = "none"; //页面隐藏
    a.href = url; // href用于下载地址
    document.body.appendChild(a); //插到页面上
    a.click(); //通过点击触发
    URL.revokeObjectURL(a.href); //释放URL 对象
    document.body.removeChild(a); //删掉a标签

代码2: 

/**
 *
 * @param {*} fileContent 文件本体
 * @param {*} _fileName 自定义文件名
 */
export const exportFileUtil = (fileContent, _fileName) => {
  const content = fileContent;
  const blob = new Blob([content], {
    type: fileContent.type || "application/octet-stream; charset=utf-8",
  });
  const fileName = _fileName;
  if ("download" in document.createElement("a")) {
    //非IE下载
    const a = document.createElement("a"); //创建一个a标签
    a.download = fileName; //指定文件名称
    a.style.display = "none"; //页面隐藏
    a.href = URL.createObjectURL(blob); // href用于下载地址
    document.body.appendChild(a); //插到页面上
    a.click(); //通过点击触发
    URL.revokeObjectURL(a.href); //释放URL 对象
    document.body.removeChild(a); //删掉a标签
  } else {
    //IE10 + 下载
    navigator.msSaveBlob(blob, fileName);
  }
};
/**
 * 
 * @param {*} res 接口返回的文件流
 */
export const dowloadFileUrl = (res) => {
  console.log(res)
  const fileNames = res.headers['content-disposition']
  if (fileNames) {
      //解码
      const fileName = decodeURIComponent(fileNames.match(/=(.*)$/)[1])
      // 处理返回的文件流
      const content = res.data
      const blob = new Blob([content], {
          // type: res.data.type||"application/vnd.ms-excel",
          type: res.data.type||"application/octet-stream; charset=utf-8"
      });
      if ('download' in document.createElement('a')) {
          //非IE下载
          const a = document.createElement('a') //创建一个a标签
          a.download = fileName //指定文件名称
          a.style.display = 'none' //页面隐藏
          a.href = URL.createObjectURL(blob) // href用于下载地址
          document.body.appendChild(a) //插到页面上
          a.click() //通过点击触发
          URL.revokeObjectURL(a.href) //释放URL 对象
          document.body.removeChild(a) //删掉a标签
      } else {
          //IE10 + 下载
          navigator.msSaveBlob(blob, fileName)
      }
  }
}

总结:

直接拼接url为下载路径,创建一个a标签触发下载;

导出接口通过接口返回的二进制流,经过出来二进制流为Blob且type类型与接口一致。 

三、补充理论知识

MIME类型是什么:点击访问

MIME类型有哪些: 点击访问

常见MIME【媒体类型】 ,如下:

扩展名----------MIME类型

  .csv--------------text/csv

  .jpeg/.jpg-------image/jpeg

  .png-------------image/png

  .rar--------------application/x-rar-compressed

  .doc-------------application/msword

  .docx-----------application/vnd.openxmlformats-officedocument.wordprocessingml.document

  .xls--------------application/vnd.ms-excel

       .xlsx------------application/vnd.openxmlformats-officedocument.spreadsheetml.sheet

  .zip--------------application/zip

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2277911.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何在谷歌浏览器中设置自定义安全警告

随着网络环境的日益复杂,浏览器的安全问题也愈发引人关注。谷歌浏览器作为一款广泛使用的浏览器,其自定义安全警告功能为用户提供了更加个性化和安全的浏览体验。本文将详细介绍如何在谷歌浏览器中设置自定义安全警告,帮助用户更好地保护自己…

AI 编程工具—Cursor进阶使用 阅读开源项目

AI 编程工具—Cursor进阶使用 阅读开源项目 首先我们打开一个最近很火的项目browser-use ,直接从github 上克隆即可 索引整个代码库 这里我们使用@Codebase 这个选项会索引这个代码库,然后我们再选上这个项目的README.md 文件开始提问 @Codebase @README.md 这个项目是用…

细说STM32F407单片机窗口看门狗WWDG的原理及使用方法

目录 一、窗口看门狗的工作原理 1、递减计数器 2、窗口值和比较器 3、看门狗的启动 4、提前唤醒中断 二、窗口看门狗的HAL驱动程序 1、窗口看门狗初始化 2.窗口看门狗刷新 3.EWI中断及其处理 三、不开启EWI的WWDG示例 1、示例功能 2、项目设置 (1&…

【Rust自学】12.6. 使用TDD(测试驱动开发)开发库功能

12.6.0. 写在正文之前 第12章要做一个实例的项目——一个命令行程序。这个程序是一个grep(Global Regular Expression Print),是一个全局正则搜索和输出的工具。它的功能是在指定的文件中搜索出指定的文字。 这个项目分为这么几步: 接收命令行参数读取…

利用rsync备份全网服务器数据

一、项目描述 某公司里有一台Web服务器,里面的数据很重要,但是如果硬盘坏了数据就会丢失,现在领导要求把数据做备份,这样Web服务器数据丢失在可以进行恢复,要求如下: 1、备份要求 每天晚上00点整在Web服…

Go基础之环境搭建

文章目录 1 Go 1.1 简介 1.1.1 定义1.1.2 特点用途 1.2 环境配置 1.2.1 下载安装1.2.2 环境配置 1.2.2.1 添加环境变量1.2.2.2 各个环境变量理解 1.2.3 验证环境变量 1.3 包管理工具 Go Modules 1.3.1 开启使用1.3.2 添加依赖包1.3.3 配置国内包源 1.3.3.1 通过 go env 配置1.…

Go Ebiten小游戏开发:贪吃蛇

贪吃蛇是一款经典的小游戏,玩法简单却充满乐趣。本文将介绍如何使用 Go 语言和 Ebiten 游戏引擎开发一个简单的贪吃蛇游戏。通过这个项目,你可以学习到游戏开发的基本流程、Ebiten 的使用方法以及如何用 Go 实现游戏逻辑。 项目简介 贪吃蛇的核心玩法是…

如何优化Elasticsearch大文档查询?

记录一次业务复杂场景下DSL优化的过程 背景 B端商城业务有一个场景就是客户可见的产品列表是需要N多闸口及各种其它逻辑组合过滤的,各种闸口数据及产品数据都是存储在ES的(有的是独立索引,有的是作为产品属性存储在产品文档上)。 在实际使用的过程中&a…

在VS2022中用C++连接MySQL数据库读取数据库乱码问题

1.正确安装mysql 安装之后的配置文件 2.在VS2022中进行相关配置 (1)右键项目,打开属性 注意是右键项目,不是.cpp文件 (2)配置属性-> VC目录 -> 包含目录 ->添加头文件路径(如图&am…

如何在linux系统上完成定时开机和更新github端口的任务

任务背景 1.即使打开代理,有的时候github去clone比较大的文件时也会出问题。这时需要每小时更新一次github的host端口; 2.马上要放假,想远程登录在学校的台式电脑,但学校内网又不太好穿透。退而求其次,选择定时启动电…

基于Java的语音陪聊软件——支持聊天私聊-礼物系统-直播系统-缘分匹配-游戏陪玩

丰富的经验、成熟的技术,打造适合当下市场发展的语音交友软件源码。Java 语言凭借其独特的优势,为这款语音陪聊软件的稳健运行和持续发展奠定了坚实基础。它不仅融合了聊天私聊、礼物系统和直播系统等实用且有趣的功能,还创新性地引入了缘分匹…

RV1126+FFMPEG推流项目(7)AI音频模块编码流程

一、AI 模块和外设麦克风的关系 AI 模块是 RV1126 芯片的一个重要组成部分。它的主要功能是将外部接入的麦克风采集到的模拟信号通过内置的驱动程序转换为数字信号。这意味着麦克风作为外设,提供音频输入信号,AI 模块通过其硬件和软件的结合&#xff0c…

计算机网络 (37)TCP的流量控制

前言 计算机网络中的TCP(传输控制协议)流量控制是一种重要机制,用于确保数据在发送方和接收方之间的传输既高效又稳定。 一、目的 TCP流量控制的主要目的是防止发送方发送数据过快,导致接收方无法及时处理,从而引起数据…

Python 实现 NLP 的完整流程

💖 欢迎来到我的博客! 非常高兴能在这里与您相遇。在这里,您不仅能获得有趣的技术分享,还能感受到轻松愉快的氛围。无论您是编程新手,还是资深开发者,都能在这里找到属于您的知识宝藏,学习和成长…

AIGC时代:如何快速搞定Spring Boot+Vue全栈开发

文章目录 一、Spring Boot基础二、Vue.js基础三、Spring Boot与Vue.js集成四、性能优化与最佳实践《快速搞定Spring BootVue全栈开发》 内容简介作者简介目录前言/序言本书内容本书特点读者对象 随着人工智能生成内容(AIGC)技术的迅速发展,…

【ArcGIS初学】产生随机点计算混淆矩阵

混淆矩阵:用于比较分类结果和地表真实信息 总体精度(overall accuracy) :指对角线上所有样本的像元数(正确分类的像元数)除以所有像元数。 生产者精度(producers accuracy) :某类中正确分类的像元数除以参考数据中该类的像元数(列方向),又称…

《探秘火焰目标检测开源模型:智能防火的科技利刃》

一、引言 火灾,如同隐藏在暗处的恶魔,时刻威胁着人们的生命财产安全与社会的稳定发展。无论是澳大利亚那场肆虐数月、烧毁约1860万公顷土地、造成近30亿只动物死亡或流离失所的森林大火,还是美国加州频繁爆发、迫使大量居民撤离家园、带来巨额…

计算机网络 (46)简单网络管理协议SNMP

前言 简单网络管理协议(SNMP,Simple Network Management Protocol)是一种用于在计算机网络中管理网络节点的标准协议。 一、概述 SNMP是基于TCP/IP五层协议中的应用层协议,它使网络管理员能够管理网络效能,发现并解决网…

Java并发03 - 无锁三大将

无锁三大将:CAS & Unsafe & Atomic 文章目录 无锁三大将:CAS & Unsafe & Atomic一:CAS机制二:Unsafe魔法指针类2.1:内存管理2.2:对象创建实例2.3:类,实例对象以及变…

JVM远程调试原理剖析

一、如何开启JVM远程调试 当一个 Java 应用启动时,JVM 会根据启动参数配置其运行环境。使用 -agentlib:jdwp 参数启动远程调试功能,JVM 会初始化调试代理。 agentlib:jdwptransportdt_socket,servery,suspendn,address*:5005 -jar your_application.jar…