vue如何读取本地文件
作者:lorogy
vue读取本地文件
前端无法像原生APP一样直接操作本地文件,否则的话打开个网页就能把用户电脑上的文件偷光了,所以需要通过用户触发,用户可通过以下三种方式操作触发:
1、通过input type=”file” 选择本地文件
2、通过拖拽的方式把文件拖过来
3、在编辑框里面复制粘贴
如果是非要不经过用户通过js读取,建议将文件放在项目static目录下,然后通过ajax请求
vue引用static下资源时,必须使用绝对路径/static/[name]
因为static目录下的文件并不会被webpack处理,它们会直接复制到最终目录(dist/static)下,一般放类库文件
1.将本地文件放在static下
2.通过get请求
因为请求的是本项目static目录下的资源,所以请求的url不需要加域名和端口(如"http:localhost:8081"),不然部署到服务器容易请求不到数据
this.$axios .get("/static/data/zt_bj_5g_location3.csv") .then(res => { let csv= res.data; console.log(csv); });
如果是部署到tomcat服务器,最好区分一下开发环境还是生产环境
const baseUrl = process.env.NODE_ENV == "development"?'':'/myprojectname'; module.exports={ baseUrl:baseUrl }
let url=baseUrl+"/static/data/zt_bj_5g_location3.csv" this.$axios .get(url) .then(res => { let csv= res.data; console.log(csv); });
vue读取本地文件踩坑
最近在做web读取本地文件的时候遇到了一些坑,在此记录下
问题
1.window.showDirectoryPicker()需要在https条件下调试
设置vue.config.js 的配置项devServer.https 为true即可
2.遍历文件夹下文件
fileTypeFilter: [ { fileType: '.json', prefixLen: 29 // base64内容前面的长度 }, { fileType: '.bin', prefixLen: 37 // base64内容前面的长度 } ], // 获取本地文件 async getLocalFile () { const dirHandle = await window.showDirectoryPicker() this.localFileList = [] this.dataStatus = common.LOCAL_DATA let realRoot = dirHandle.name if (realRoot == 'RawInfo') { realRoot = 'client' } if (realRoot != '') { this.getChild(dirHandle, realRoot, this.localFileList) } }, // 遍历文件夹获得所有文件的路径 async getChild (dirHandle, root, ret) { if (dirHandle.kind != 'directory') { return } for await (const entry of dirHandle.values()) { if (entry.kind == 'directory') { this.getChild(entry, root + '/' + entry.name, ret) } else { const file = await entry.getFile() if (this.getFilePrefixLen(entry.name) != -1) { ret.push(root + '/' + entry.name) this.readFile(root + '/' + entry.name, file) } } } }, getFilePrefixLen (fileName) { let len = -1 this.fileTypeFilter.forEach((value) => { if (fileName.search(value.fileType) != -1) { len = value.prefixLen return } }) return len },
3.读取文件时,onload为异步执行
注意,虽然bin文件用readAsDataURL也能读取到内容,但是试了几次了发现,bin文件中可能会有些字符在转换的时候有问题,比如出现 EF BF BD 等(这个是无效字符的替换)字符,其实对应过去只有一个字节,导致bin文件最终不一致,所以bin文件最好还是直接用readAsArrayBuffer 读取,然后直接用gzip进行压缩,这样就可以无损还原了
async readFile (fileName, file) { let fileInfo = common.getFileInfo(fileName) // bin文件用ArrayBuffer读取,防止有乱码出现 // json用dataUrl读取 let read = new FileReader(); if (fileName.indexOf(".bin") !== -1) { read.readAsArrayBuffer(file); } else { read.readAsDataURL(file); } // read读取完毕回调 read.onload = (e) => { // bin文件用 if (fileName.indexOf(".bin") !== -1) { let buffer = new Uint8Array(read.result); fileInfo.content = common.zip(buffer) } else { fileInfo.content = read.result.substr( this.getFilePrefixLen(fileName), read.result.length ) fileInfo.content = common.zip(Base64.decode(fileInfo.content)) } }; },
4.pako.js库使用
注意,此方法规避了pako压缩后中文乱码的问题,网上其他方法很多是有问题的,还有就是json压缩的问题,一般来说有几种方法,
最简单的就是用
JSON.stringify
把格式(空格和换行)去掉, 另外就是采用压缩,比如pako
export function unzip (b64Data) { let charData = atob(b64Data).split('').map(function (x) { return x.charCodeAt(0); }); let binData = new Uint8Array(charData); return pako.inflate(binData, { to: 'string' }); } export function zip (str) { let binaryString = pako.gzip(str); let a = Array.from(binaryString); let s = ""; a.forEach((item, index) => { s += String.fromCharCode(item) }) return btoa(s) }
后端go解压缩代码
// 内置包 "compress/gzip" // gzip压缩 func GzipEncode(input []byte) ([]byte, error) { // 创建一个新的 byte 输出流 var buf bytes.Buffer // 创建一个新的 gzip 输出流 gzipWriter := gzip.NewWriter(&buf) // 将 input byte 数组写入到此输出流中 _, err := gzipWriter.Write(input) if err != nil { _ = gzipWriter.Close() return nil, err } if err := gzipWriter.Close(); err != nil { return nil, err } // 返回压缩后的 bytes 数组 return buf.Bytes(), nil } // gzip解压缩 func GzipDecode(input []byte) ([]byte, error) { // 创建一个新的 gzip.Reader bytesReader := bytes.NewReader(input) gzipReader, err := gzip.NewReader(bytesReader) if err != nil { return nil, err } defer func() { // defer 中关闭 gzipReader _ = gzipReader.Close() }() buf := new(bytes.Buffer) // 从 Reader 中读取出数据 if _, err := buf.ReadFrom(gzipReader); err != nil { return nil, err } return buf.Bytes(), nil }
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。