前端下载文件或者图片方式,window.open或者a标签形式
首先分别讲一下下载文件的方式都有哪些
1.通过a标签的方式下载文件
<a href="http://www.baidu.com" download="baidu.html">下载</a>
我们点击下载,发现是跳转到了百度的首页,并没有真的下载文件。
因为a
标签下载只能下载同源
的文件;如果是跨域
的文件,比如图片、音视频等媒体文件等都无法使用上面的a
标签方式下载。
上面的代码是直接通过书写a
标签来实现文件下载;我们也可以通过js
来实现,代码如下:
const a = document.createElement('a')
a.href = 'http://www.baidu.com'
a.download = 'baidu.html'
a.click()
效果和上面的一样,都是跳转到百度的首页,没有下载文件。
这里的重点是a标签的download属性,这个属性是HTML5新增的。
它的作用是指定下载的文件名,如果不指定,那么下载的文件名就会根据请求内容的Content-Disposition来确定,如果没有Content-Disposition,那么就会使用请求的URL的最后一部分作为文件名。
2. 使用 window.open 下载
上面使用a
标签的案例也可以通过window.open
来实现,效果是一样的,代码如下:
window.open('http://www.baidu.com', '_blank')
这里的_blank
是指定用浏览器新窗口打开链接;如果不指定,那么就会在当前页面打开。
同样a
标签的download
属性也是可以使用的,代码如下:
window.open('http://www.baidu.com', '_blank', 'download=baidu.html')
当然这种方式也是有缺陷的,对比于a
标签,window.open
方式不能下载.html
、.htm
、.xml
、.xhtml
等文件;因为这些文件会被当成html
文件来处理,所以会直接在当前页面打开。
同样也不能下载跨域
的文件,这个是window.open
实现下载原理决定的。
3. XMLHttpRequest
这种方式就是我们常说的ajax
下载,包括Axios
、Fetch
等,代码如下:
const xhr = new XMLHttpRequest()
xhr.open('GET', 'http://www.baidu.com')
xhr.send()xhr.onload = function () {const blob = new Blob([xhr.response], { type: 'text/html' })const a = document.createElement('a')a.href = URL.createObjectURL(blob)a.download = 'baidu.html'a.click()
}
这里关于XMLHttpRequest相关的知识就不做展开了,只讲和文件下载相关的部分。
上面代码主要的逻辑是当我们的请求成功后,我们会拿到响应体Response,这个Response就是我们要下载的内容。
然后我们把它转换成Blob对象,通过URL.createObjectURL来创建一个URL,最后使用a标签的download属性来实现文件下载。
4.Blob 对象
下面是MDN对Blob对象的定义:
Blob对象表示一个不可变、原始数据的类文件对象。
Blob的数据可以按文本或二进制的格式进行读取,也可以转换成ReadableStream来用于数据操作。
Blob表示的不一定是JavaScript原生格式的数据。
File接口基于Blob,继承了Blob的功能并将其扩展以支持用户系统上的文件。
Blob对象是html5新增的对象,它的作用是用来存储二进制数据的,比如图片、视频、音频等,它的使用方法如下:
/*** @param {Array} array 二进制数据* @param {Object} options 配置项* @param {String} options.type 文件类型,它代表了将会被放入到 blob 中的数组内容的 MIME 类型。* @param {String} options.endings 用于指定包含行结束符\n的字符串如何被写入。默认为transparent,表示不会修改行结束符。还可以指定为native,表示会将\n转换为\r\n。*/
const blob = new Blob([], { type: '' })
Tips:需要关注的是type
属性,默认情况下, Blob
对象是没有type
属性的,那么这个Blob
就是一个无类型的Blob
,文件不会损毁,但是无法被正常识别。
5.URL.createObjectURL
下面是MDN对 URL.createObjectURL方法的定义:
URL.createObjectURL()静态方法会创建一个DOMString,其中包含一个表示参数中给出的对象的URL。
这个URL的生命周期和创建它的窗口中的document绑定。
这个新的URL对象表示指定的File对象或Blob对象。
这个方法是用来创建一个URL的,它的作用是把一个Blob对象转换成一个URL,这个URL可以用来下载文件,也可以用来预览文件,代码如下:
const url = URL.createObjectURL(blob)
这里需要注意的是,这个URL
的生命周期和创建它的窗口中的document
绑定。
也就是说,当我们的document
被销毁后,这个URL
就会失效,所以我们需要在合适的时机销毁它。
代码如下:
URL.revokeObjectURL(url)
回到我们刚才下载的问题,我们是通过Blob对象来解决,但是我们的type属性是写死的,如果在文件类型是确定的情况下是没问题的。
但是如果这个接口就是下载文件的接口,文件可能是各种类型的,我们应该怎么处理?
这里的没有正确答案,第一个可以和接口提供者进行协商,协商方案是不确定的;第二就是通过Response的header来获取文件的type,也是我们要讲的:
const type = response.headers['content-type']
const blob = new Blob([response.data], { type })
这里我们通过Response的header来获取type,然后再创建Blob对象,这样就可以正确的下载文件了。
其实content-type也可能是application/octet-stream,这个时候我们就需要通过file-type来获取文件的type了。
下面的代码是通过file-type来获取文件的type:
import {fileTypeFromStream} from 'file-type';const type = await fileTypeFromStream(response.body);
const blob = new Blob([response.data], { type })
6. 总结
上面的方案这么多,其实最终还是落到a
标签上,所以不管是通过浏览器的内置行为进行下载,还是通过ajax
进行下载,文件下载的最终还是浏览器的行为。
我项目中遇到的需求如下:
首先window.open(URL)的这种方式和a标签方式一样对于pdf和图片都会打开文件,而并非直接下载,那么当然如果自动打开pdf或者图片,鼠标右击图片或者pdf右上角也会有下载入口。但是如果说需求是点击按钮直接下载文件,那么需要采取获取文件流然后拿到文件流通过a标签下载这种当时,当然获取文件流可以前端去做也可以后端做。
本次需求是通过oss的URL来下载文件。那么我选择前端去做获取文件二进制流。
const downFile = (fileUrl) => {console.log(fileUrl); // fileUrl是oss的url字符串// ********* 方式一 ************// window.open(fileUrl) //window.open的方式// ********* 方式二 ************// let a = document.createElement("a") //直接a标签的方式// a.download = 'aaa'// // a.href = window.URL.createObjectURL(blob)// a.href = fileUrl// a.click()// a.remove()// ********* 方式三 ************//直接下载文件并且前端获取文件二进制流const xhr = new XMLHttpRequest();xhr.open('GET', fileUrl, true);xhr.responseType = 'blob'; // 获取文件blob数据xhr.onload = function () {if (xhr.status !== 200) {ElMessage({type: 'error',message: `下载出现错误`,})return;}const newUrl = window.URL.createObjectURL(xhr.response); // 生成一个可用的临时urlconst a = document.createElement('a'); // 生成a标签调用点击事件a.setAttribute('href', newUrl);a.setAttribute('target', '_blank');a.setAttribute('download', fileName); // 自定义文件名document.body.appendChild(a);a.click();document.body.removeChild(a);};xhr.send();
}
感谢这位作者的分享,收获良多,特此记录。
https://juejin.cn/post/7254143696483991611
相关文章:
前端下载文件或者图片方式,window.open或者a标签形式
首先分别讲一下下载文件的方式都有哪些 1.通过a标签的方式下载文件 <a href"http://www.baidu.com" download"baidu.html">下载</a> 我们点击下载,发现是跳转到了百度的首页,并没有真的下载文件。 因为a标签下载只能…...
webpack配置scss loader
国内GPT站点:https://www.atalk-ai.com 在 Webpack 中配置 sass-loader 用于处理 .scss 文件通常涉及以下步骤: 安装必要的依赖: 你需要安装 sass-loader,以及 sass 本身(sass 是 node-sass 的替代品,更快且…...
k8s有状态部署mysql主从(local pv持久化)
1、修改自己对应的命名空间 2、local pv的方式必须先创建好目录在给权限 3、sts部署文件密码都要修改好在部署 yaml资源文件如下: #配置mysql的root密码再部署,如果部署了在修改root密码就会失败,必须在初始化就把root密码修改好 #部署采…...

下载并安装anaconda和VScode,配置虚拟环境,并使用VScode运行代码
文章目录 前言软件下载Anaconda下载VScode下载 软件安装Anaconda安装Vscod安装 配置虚拟环境并运行代码Anaconda创建环境VScode使用,运行代码1. 打开代码所在文件夹2. 选择解释器3. 运行代码 总结 前言 运行python代码,需要2个软件如下: Ana…...

拼图 游戏
运行出的游戏界面如下:按住A不松开,显示完整图片;松开A显示随机打乱的图片 User类 package domain;/*** ClassName: User* Author: Kox* Data: 2023/2/2* Sketch:*/ public class User {private String username;private String password;p…...

python循环语句和函数
1.使用for循环打印9*9乘法表 for i in range(1, 10):for j in range(1, i1):print(i, "*", j, "", i*j, end"\t")print()结果: 2.使用while循环打印9*9乘法表 i 1 while i < 10:j 1while j < i1:print(i, "*", j…...
php框架dcat-admin速查笔记
要想灵活的使用dcat-admin框架开发,必须知道框架有哪些类提供给我们使用. 每一个自定义的按钮,弹框,信息展示,小组件都用到特定的类和接口. 常用核心类 Dcat\Admin\Http\Controllers\AdminController 需要继承的公共控制器 Dcat\Admin\Layout\Content 布局核心 Dcat\Admin\Gr…...

【Java】文件I/O-文件内容操作-输入输出流-Reader/Writer/InputStream/OutputStream四种流
导读 在文件I/O这一节的知识里,对文件的操作主要分为两大类: ☑️针对文件系统进行的操作 ☑️针对文件内容进行的操作 上文已经讲了针对文件系统即File类的操作,这篇文章里博主就来带了解针对文件内容的操作,即输入输出流&am…...

rocky8.9配置K8S集群kubernetes,centos同理
注意!!! 虚拟机实验环境不要使用’克隆’!!! 唯一标识冲突:K8S集群中的每个节点都需要具有唯一的标识符,例如节点名称、IP地址、MAC地址等。当克隆虚拟机时,这些唯一标识…...

Linux下的文件IO之系统IO
1. 知识点 读入写出,切记以我们程序为中心向文件或者别的什么东西读入写出(输入流输出流) 人话就是 文件向我们程序就是读入 程序向文件或者别的什么就是写出 2. open打开文件 open.c /****************************************************…...

iptables防火墙之SNAT与DNAT
1. SNAT SNAT 应用环境:局域网主机共享单个公网IP地址接入Internet (私有IP不能在Internet中正常路由) SNAT原理:源地址转换,根据指定条件修改数据包的源IP地址,通常被叫做源映射。 数据包从内网发送到公网时,SNAT会把数据包的源IP由私网IP…...
Python与设计模式--命令模式
23种计模式之 前言 (5)单例模式、工厂模式、简单工厂模式、抽象工厂模式、建造者模式、原型模式、(7)代理模式、装饰器模式、适配器模式、门面模式、组合模式、享元模式、桥梁模式、(11)策略模式、责任链模式、命令模式、中介者模…...

uni-app 自带返回方法onBackPress,返回上一级并且刷新页面内容获取最新的数据
onBackPress 返回上一级并且刷新页面内容获取最新的数据 onBackPress 方法是uinapp自带返回键方法,也就是在app和H5返回键 onBackPress() {setTimeout(() > {uni.switchTab({url: /pages/Users/index,})}, 300)return true}, methods: {}在这里 uni.switchTab…...

python用YOLOv8对图片进行分类
用yolov8的模型进行分类 先上效果图 图片资源 模型下载地址 https://github.com/ultralytics/ultralytics 代码 import matplotlib.pyplot as plt from ultralytics import YOLO from PIL import Image import cv2model YOLO(../ultralytics/yolov8n.pt)# print(model…...
Spring中@DependsOn 使用详解
一、注解源码 Target({ElementType.TYPE, ElementType.METHOD}) Retention(RetentionPolicy.RUNTIME) Documented public interface DependsOn {String[] value() default {}; } 二、基础概念 DependsOn是Spring框架用来指定bean之间依赖关系的注解之一,即可用户类…...
android笔记 SELinux
1.SELinux解错步骤 log信息: 11-20 02:25:12.526 8976 8976 W om.jzzh.setting: type1400 audit(0.0:1316): avc: denied { write } for name"com.jzzh.setting-IWLR9dkz8TWizbNujdTpWw" dev"mmcblk2p15" ino2661 scontextu:r:system_app:s0…...

vue3 keep-alive页面切换报错:parentComponent.ctx.deactivate is not a function
问题: <router-view v-slot"{ Component }"><keep-alive ><component :is"Component" v-if"$route.meta.keepAlive" /></keep-alive><component :is"Component" v-if"!$route.meta.keepA…...
prompt提示
用例生成 # 任务描述 作为一个高级c程序员,需要完成下列功能的gtest测试用例 # 功能描述 给定两个数字型字符串s1和s2,求和,返回值也是字符串 # 接口举例 调用strAdd("123", "132"),输出“255” # 输出要求 - 入参为空串、nu…...

边缘计算网关:智能制造的“智慧大脑”
一、智能制造的崛起 随着科技的飞速发展,智能制造已经成为了制造业的新趋势。智能制造不仅能够提高生产效率,降低生产成本,还能够实现个性化定制,满足消费者多样化的需求。然而,智能制造的实现离不开大量的数据处理和分…...

HNCTF2022Week1 Reverse WP
文章目录 [HNCTF 2022 Week1]超级签到[HNCTF 2022 Week1]贝斯是什么乐器啊?[HNCTF 2022 Week1]X0r[HNCTF 2022 Week1]你知道什么是Py嘛?[HNCTF 2022 Week1]CrackMe[HNCTF 2022 Week1]给阿姨倒一杯Jvav[HNCTF 2022 Week1]Little EndianNSSCTF{Littl3_Endi…...
进程地址空间(比特课总结)
一、进程地址空间 1. 环境变量 1 )⽤户级环境变量与系统级环境变量 全局属性:环境变量具有全局属性,会被⼦进程继承。例如当bash启动⼦进程时,环 境变量会⾃动传递给⼦进程。 本地变量限制:本地变量只在当前进程(ba…...

centos 7 部署awstats 网站访问检测
一、基础环境准备(两种安装方式都要做) bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats࿰…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止
<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet: https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...

汽车生产虚拟实训中的技能提升与生产优化
在制造业蓬勃发展的大背景下,虚拟教学实训宛如一颗璀璨的新星,正发挥着不可或缺且日益凸显的关键作用,源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例,汽车生产线上各类…...
渲染学进阶内容——模型
最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)
笔记整理:刘治强,浙江大学硕士生,研究方向为知识图谱表示学习,大语言模型 论文链接:http://arxiv.org/abs/2407.16127 发表会议:ISWC 2024 1. 动机 传统的知识图谱补全(KGC)模型通过…...
Spring Boot面试题精选汇总
🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...
今日科技热点速览
🔥 今日科技热点速览 🎮 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售,主打更强图形性能与沉浸式体验,支持多模态交互,受到全球玩家热捧 。 🤖 人工智能持续突破 DeepSeek-R1&…...

VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP
编辑-虚拟网络编辑器-更改设置 选择桥接模式,然后找到相应的网卡(可以查看自己本机的网络连接) windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置,选择刚才配置的桥接模式 静态ip设置: 我用的ubuntu24桌…...

视觉slam十四讲实践部分记录——ch2、ch3
ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...