Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

下载文件 和 链接跳转(打开新窗口被拦截),没关系的! #2

Open
ohhoney1 opened this issue Sep 1, 2018 · 0 comments
Labels
summary Summary notes about one problem

Comments

@ohhoney1
Copy link
Owner

ohhoney1 commented Sep 1, 2018

问题来源

开发中,各种log下载到本地的需求特别多,由于交互方式各不相同,封装了一个方法,专门用来处理文件的下载。这个也比较常见,就是通过a标签处理:

export function handleDownload(url) {
  const a = document.createElement('a')
  const $body = document.body

  a.href = url
  // a.target = '_blank'
  a.style.display = 'none'
  $body.appendChild(a)
  a.click()
  $body.removeChild(a)
}

这种下载文件的方式有个前提:后端已对接口的返回数据做了处理,相应的响应头见下图:
image
主要在content-type:"application/octet-stream",告诉浏览器这是字节流,浏览器对此的操作默认是下载。

问题来了

代码简单,可问题就出现在a.target = '_blank'这句。没注释之前,下载的时候会新开一个页面,然后下载,页面关闭。
突然有次,浏览器阻止了新开的页面,自然而然下载不了了,然后...然后就有个这个笔记。

下载文件的问题

问题来源里已经给出一个下载字节流的方式,还有几种方式:

  • window.open()方法
  • 动态创建form,模拟表单提交操作

对于非文本流的下载,H5里,给a标签提供了downlaod属性,见张鑫旭的文章——JS前端创建html或json文件并浏览器导出下载,文章详细介绍了借助downloadBlobBase64三种方式,实现文件下载功能,但是IE系列全军覆没。

浏览器打开新页面问题

上面啰里啰嗦描述了本人的误解,把下载文件和打开新页面混为一谈了,可能那天敲代码迷糊了。下面简单总结下浏览器打开新页面的问题。

浏览器阻止新建页面,这个问题太常见了,这其实也不算问题,是现阶段各浏览器厂商的一个基本安全策略,为此,js被广告商滥用的时代也结束了。
可是,各种需求积压过来了,需要前端不得不做一些新建页面跳转的功能。常见的一些方式有:

  1. 上面下载的方法是一种,打开新页面要加上 a.target = '_blank'
  2. 使用window.open,异步打开新页面时,为了防止浏览器拦截,可以这样做
function openNewWindow() {
  window.open('/')
  http.get(url).then(() => {
    window.location.href = url
  })
}

对于第二种方法,有一个疑问。见问题js打开新窗口被拦的问题,其中有提到非异步加载时,直接点击同步请求时即可正常跳转。后面用setTimeout模拟异步请求,发现临界值点是1000ms,小于1000ms的setTimeout异步可以正常跳转。但是ajax请求和这个数字没关系了——不管是多少ms,结果都是被拦截。
后网上查阅资料,window.open() 某些情况会被浏览器阻止弹出窗口博文里很详细的介绍了window.open方法,其中提供了一种对于浏览器拦截时的提示方案:

var windowOpen = window.open('http://lingyi.red/', 'lingyired', 'status=no,menubar=no,titlebar=no,toolbar=no,directories=no, width=800,height=600, top=0, left=0')
// 利用返回值来判断 window.open 操作是否被正常地执行 
if (windowOpen == null || typeof(windowOpen)=='undefined'){
  $('#feedback').html('已触发:窗口无法打开,请检查你的浏览器设置。')
} else {
  $('#feedback').html('已触发:窗口打开成功了')
} 

总结

做的是下载文件的功能,排查问题时居然一直搜索浏览器阻止新页面打开的问题。其实这两个功能没关系,唯一的相同点是动态创建a标签,这里把自己迷惑住了而已。对每一句代码都应该思考其存在的意义,不写冗余代码,不偷工减料。

真是“基础不牢,地动山摇”。

@ohhoney1 ohhoney1 added the summary Summary notes about one problem label Sep 1, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
summary Summary notes about one problem
Projects
None yet
Development

No branches or pull requests

1 participant