上传与下载
首先要了解数据转换
图片来源 (https://shanyue.tech/post/binary-in-frontend/#%E6%95%B0%E6%8D%AE%E8%BE%93%E5%85%A5)
下载
- 关于 application/octet-stream 和 Content-Disposition
浏览器并不认得这是什么类型,也不知道应该如何展示,只知道这是一种二进制文件,因此遇到content-type为application/octet-stream的文件时,浏览器会直接把它下载下来。这个类型一般会配合另一个响应头Content-Disposition,该响应头指示回复的内容该以何种形式展示,是以内联的形式(即网页或者网页的一部分),还是以附件的形式下载并保存到本地。
/**
* 使用a标签下载一个文件
* @param {} url 下载文件的接口路径(可以提交要下载文件的名称来修改下载文件的路径) 或者 下载文件的路径(不能修改下载文件的名称)
* 例如:http://xx/xxx/xxx/download?filename='123' 或者 http://xx/xxx/xxx/download/123.pdf
*/
export const createIFrameDownLoad = (url) => {
const iframeDom = document.createElement('iframe')
iframeDom.style.zIndex = -100
iframeDom.style.position = 'fixed'
document.body.insertBefore(iframeDom, document.body.children[0])
const iframeWin = iframeDom.contentWindow // 1.获取iframe中的window
const iframeDocs = iframeWin.document // 2.获取iframe中的document
iframeDocs.write(`<!doctype html>`)
iframeDocs.write(`
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<a href="${url}" target="_self" id="downLoad" ></a>
</body>
</html>
`)
const a = iframeDocs.querySelector('#downLoad')
a.click()
setTimeout(() => {
document.body.removeChild(iframeDom)
}, 10000)
}
/**
*
* @param {} src 文件路径 'https://dakaname.oss-cn-hangzhou.aliyuncs.com/file/2018-12-28/1546003282521.pdf'
* @param {} name
*/
export const downFile = function(src, name = '') {
// 下载非同源图片
const x = new XMLHttpRequest()
// 禁止浏览器缓存;否则会报跨域的错误
x.open('GET', src, true) // 打开对象,也可以说是设置参数
x.responseType = 'blob'
x.onload = function(e) {
// 异步请求加载完成后所执行的函数
const url = window.URL.createObjectURL(x.response)
const a = document.createElement('a')
a.href = url
a.download = name
a.click()
}
x.send()
}
/**
* 注意 axios 需要添加 :responseType = 'blob'
* @param {*} content 文件流内容
* @param {*} name 文件的名称
*/
export const downLoadFileByStream = (content, name, type = '.xls') => {
var elink = document.createElement('a')
// name为后台返给前端的文件名,后缀名必须加,后台有返回后缀就不用管,不然下载在本地不好打开。
elink.download = name + type
elink.style.display = 'none'
var blob = new Blob([content])
elink.href = URL.createObjectURL(blob)
document.body.appendChild(elink)
elink.click()
setTimeout(() => {
document.body.removeChild(elink)
}, 10000)
}
export const downloadfile = (res) => {
var blob = new Blob([res.data], { type: 'application/octet-stream;charset=UTF-8' })
var contentDisposition = res.headers['content-disposition']
var patt = new RegExp('filename=([^;]+\\.[^\\.;]+);*')
var result = patt.exec(contentDisposition)
var filename = result[1]
var downloadElement = document.createElement('a')
var href = window.URL.createObjectURL(blob) // 创建下载的链接
var reg = /^["](.*)["]$/g
downloadElement.style.display = 'none'
downloadElement.href = href
downloadElement.download = decodeURI(filename.replace(reg, '$1')) // 下载后文件名
document.body.appendChild(downloadElement)
downloadElement.click() // 点击下载
document.body.removeChild(downloadElement) // 下载完成移除元素
window.URL.revokeObjectURL(href)
}
上传
上传经常要配和对话框进行文件上传进度展示
目前接触到的上传基本为multipart/form-data(二进制文件上传)
基本用的是FormData的API,而上传需要处理的更多的是文件的类型筛选和进度展示,中断,重传,拖拽等
节流与防抖
防抖:对于短时间内连续触发的事件(如滚动事件,按钮提交),防抖的含义就是让某个时间期限(如500毫秒)内,事件处理函数只执行一次(最后一次)
ex:滚动事件用防抖打印console.log只会出现一次
/**
* 防抖函数 -> 会把前一个清除
* @param method 事件触发的操作
* @param delay 多少毫秒内连续触发事件,不会执行(默认500毫秒)
* @returns {Function} handleInput:debounce(function(val){}){ console.log(val) }
*/
const debounce = (method, delay) => {
delay = delay || 500
let timer = null
return function() {
const self = this
const args = arguments
timer && clearTimeout(timer)
timer = setTimeout(function() {
method.apply(self, args)
}, delay)
}
}
节流:如果短时间内大量触发同一事件,那么在函数执行一次之后,该函数在指定的时间期限内不再工作,直至过了这段时间才重新生效(类似开关)。
ex:滚动事件用节流打印console.log,每500ms会出现一次
function throttle(fn,delay=500){
let valid = true
return function() {
const self = this
const args = arguments
if(!valid){
//休息时间 暂不接客
return false
}
// 工作时间,执行函数并且在间隔期内把状态位设为无效
valid = false
setTimeout(() => {
fn.apply(self,args)
valid = true;
}, delay)
}
}