文件操作与文件上传
一、前端把一个文件上传到后端的方案
- 二进制blob传输 【formData传输】 【相当于用formData,搭载了blob传输给了后端】
- base64传输 【转为base64传输,后端解码后,再转回base64】【使用了fileReader】
二、相关对象
- files 通过input标签读过来的文件对象
- blob 不可变的二进制内容,包含很多操作方法
- formData 用于和后端传输的对象
- fileReader 多用与把文件读取为某种形式,如base64,text文本
三、文件对象之间的关系
说明1:
说明2:
说明3:
fr.onload = function(){
console.log(fr.result)
}
async submit(){
let _formData = new FormData()
_formData.append('file',file对象)
}
axios.post('接口',_formData)
四、多文件上传
五、切片上传
let fileObj
let percent = 0
fileChange(e){
fileObj = e.target.files[0]
}
async submit(){
let size = 2*1024*1024
let current = 0
let fileSize = fileObj.size
while(current < fileSize){
let _formData = new FormData()
_formData.append(_formData.name,fileObj.slice(current,current+size))
await axios.post('/api',_formData)
percent = Math.min((current/fileSize)*100,100)
current+=size
}
file.slice()
}
六、断点续传
利用localStorage,结合切片上传实现
localStorage.setItem(fileObj,current)
文件下载【前端接受后端传输文件】
一、从后端获取到的二进制文件下载下来有三种方案
- 直接打开下载
- 利用a标签的download
- file-saver
方案一:直接打开下载
window.open('http://api.xxx')
方案二:利用a标签的download,比较合适的方法
一、 重要的概念:
- createObjectURL:把blob对象的内容地址,以url形式给出
- msSaveBlob:IE不支持a标签下载,用的是msSaveBlob
- a标签的download属性,表面该a标签的i行为是下载,并说明文件名
二、流程总结
//方案一:
1. 按照blob请求接口(必须按blob接受二进制文件)
2. 判断有没有msSaveBlob
3. 若有则用msSaveBlob下载,若没有则用以下流程
//方案二:
//没有msSaveBlob的流程
1. createObjectURL创建文件本地url
2. 创建a标签
3. 创建url给到a标签的href
4. 设置download
5. 模拟点击a标签
6. 下载完成
三、具体实现代码
axios.get('api',{responseType:'blob'}).then(res=>{
console.log(res.data)
if(window.navigator.msSaveBlob){
window.navigator.msSaveBlob(res.data,{type:'blob类型,具体看请求接口的type救好'},'文件名.ppt')
}else{
let blobURL = URL。createObjectURL(res.data)
let link = document。createElement('a')
link.href = blobURL
a.download = 'text.ppt'
link.style.display = 'none'
link.click()
URL.revokeObjectURL(blobURL)
}
})
四、使用第三方插件库,file-saver
import {saveAs} from 'file-saver'
axios.get('api',{responseType:'blob'}).then(res=>{
saveAs(res.data,'文件名.ppt')
})
扩展:比如收到后端的文件流之后,把其展示出来,而不是下载 (即,直接预览)
- 流程梳理
预览,就是需要一个地址
无论是,图片、excel、word等,总而言之就是给一个地址
url除了线上地址,还有base64URL
word和excel
一、 excel
解析内容
- 通用 - xlsx
- vue - xlsx
- react - xlsx
预览
- 通用 - xlsx
- vue - @vue-office/excel
- react - react-file-viewer
场景一:将excel转换为数据
- 本地选择文件 -> 读取为前端html和数据对象
使用xlsx库
import {read,writeFile,utils} from 'xlsx'
1. 选择文件后,获取文件对象:let file = e.target.files[0]
2. 将blob对象转换为arrayBuffer,并且调用read方法生成book对象:
file.arrayBuffer().then(res=>{
const wb = read(res)
const sheet1 = wb.Sheets.Sheet1
const data = utils.sheet_to_json(sheet1)
const _html = utils.sheet_to_html(sheet1)
})
- 请求后端接口 -> 读取为前端html和数据对象
// 为了能从接口获取到blob数据,需要设置响应头
axios.get('http://api',{responseType:'blob'}).then(res=>{
//下面这些操作和上面本地选择的方式一样
file.arrayBuffer().then(res=>{
const wb = read(res)
const sheet1 = wb.Sheets.Sheet1
const data = utils.sheet_to_json(sheet1)
const _html = utils.sheet_to_html(sheet1)
})
})
场景二:将数据转换为excel
- 把前端的一个table dom转化为excel
- 把一个前端对象转换为excel
方式一:
let a=[
{name:'sss',id:1000,score:99},
{name:'rrr',id:2000,score:99}
{name:'hhh',id:3000,score:99}
]
const ws = utils.json_to_sheet(a);
const wb = utils.book_new()
utils.book_append_sheet(wb,ws,'sheet1')
writeFile(wb,'text1.xlsx')
方式二:将table dom 转换为excel
const tableDom = this.$refs.excelTable
const ws=utils.table_to_sheet(tableDom)
const wb = utils.book_new()
utils.book_append_sheet(wb,ws,'sheet2')
writeFile(wb,'text2.xlsx')
const wb=utils.table_to_book(tableDom)
@vue-office/excel插件的使用
import vueofficeExcel from '@vue-office/excel'
vueofficeExcel 这是一个组件
<vueofficeExcel :src='' style="height:500px">
let file = e.target.files[0]
const fr = new FileReader()
fr.readAsDataURL(file);
fr.onload = (e)=>{
src = e.target.result
}
二、word
解析内容
- 通用 - docxtemplater
- vue - docxtemplater
- react - docxtemplater
预览
- 通用 - mammoth 或 docx-preview
- vue - @vue-office/docx
- react - react-file-viewer
@vue-office/docx插件的使用
import vueofficedocx from '@vue-office/docx'
vueofficedocx 这是一个组件
<vueofficedocx :src='wordPath' style="height:500px">
let file = e.target.files[0]
const fr = new FileReader()
fr.readAsDataURL(file);
fr.onload = (e)=>{
wordPath = e.target.result
}
docx-preview 通用插件方法
import {renderAsync} from 'docx-preview'
let file = e.target.files[0]
let dom = this.$ref.xxx
renderAsync(file,dom)