本文属于踩坑文章,去网上找了好久没翻到相关的文章,相当头大。然后uniapp的文档做的也很垃圾,没法综合的看,有很多接口是要用HTML5+ API Reference里给定的接口的。
我本身是要做一个移动端的绘制图表的课设,画图打算用echarts。因为我设定好要能够解析xlsx,一定要用到相关的解析工具。
坑点一、uni接口打开文档需要第三方应用(Android)
我在找数据的获取的解决方案的时候看到这么一个方案,试了一下直接报错,错误原因是没有相关的第三方服务,当然这点在官方文档里可以翻到。因为用不到所以没去记这个api,知道android不能用就行
坑点二、文档分散
众所周知uniapp是可以打包成app的,然后就是app的话一般都会有一个本地的sqlite存储库,然后像访问本地啊,sqlite存储库之类的都是要用上面那个网址里文档找出来的。然后他这个文档......怎么说呢,用着很不方便,导航不会固定侧边显示......
回到正题,我们解决xlsx在uniapp上如何读取本地文件
解决方案
思路就是通过plus提供的文件访问,生成base64码,然后通过正则匹配去掉base64识别头,将最后的字符串交给xlsx处理。
const nameModel = /.+\.(xlsx|xls)/g;
const AndroidData = '/storage/emulated/0/Android/data';
const weChatData = '/com.tencent.mm/MicroMsg/Downloal';
const QQData = '/com.tencent.mobileqq/Tencent/QQfile_recv';
const dataDir = [weChatData, QQData];
const Browser = '/storage/emulated/0/Download/browser'
const getPathFiles = (fileURL,files) => {
/**
* PUBLIC_DOCUMENTS
* PUBLIC_DOWNLOADS
*/
plus.io.resolveLocalFileSystemURL( fileURL, function( fs ) {
// 可通过fs进行文件操作
if (fs.isDirectory) {
const directoryReader = fs.createReader();
directoryReader.readEntries((entries) => {
for(let i=0;i<entries.length;i++){
const entry = entries[i];
console.log(entry.name)
if(entry.isFile&&nameModel.test(entry.name)){
files.push(entry)
console.log('get a XLSfile')
}
}
console.log(files.length)
// return files;
})
}
// console.log( "Request file system success!" );
}, function ( e ) {
console.log( "Request file system failed: " + e.message );
// return files;
} );
// return files
}
export const getFamiliarFiles = (arr) => {
const AllPromise = []
for(let i=0;i<dataDir.length;i++){
AllPromise.push(getPathFiles(AndroidData+dataDir[i],arr));
}
AllPromise.push(getPathFiles(Browser,arr));
return Promise.all(AllPromise).then(()=> {
/* const result = []
for(let i=0;i<res.length;i++){
console.log(...res)
result.push(...res)
}
console.log(result.length)
for(let i=0;i<result.length;i++){
console.log(result[i])
} */
return 'allget';
}).catch((err)=> {
return err;
})
}
这段代码主要是先获取到本地的excel文件列表,文件的读取还没有整理进来
import * as XLSX from 'xlsx/dist/xlsx.core.min';
//此为主要代码
export const readWorkbookFromLocalFile = (file, callback) => {
const model = /.*base64,/
const newFile = file.replace(model, '');
console.log(model.test(file))
console.log(typeof newFile)
const workbook = XLSX.read(newFile, {type: 'base64'})
console.log(workbook);
}
//这部分没用
export const readByXlsx = (fullPath) => {
const workbook = XLSX.readFile(fullPath);
console.log(workbook);
}
xlsx的识别代码
import { getFamiliarFiles } from '/Tool/getFile/index.js'
import { readWorkbookFromLocalFile, readByXlsx } from '/Tool/getXlsx/index.js'
const arr = [];
getFamiliarFiles(arr).then(() => {
setTimeout(() => {
console.log(arr)
for(let i =0;i<arr.length;i++){
arr[i].file((file) => {
const reader = new plus.io.FileReader();
console.log(reader)
reader.onloadend = (e) => {
console.log( e.target.result );
readWorkbookFromLocalFile(e.target.result)
}
reader.readAsDataURL( file );
})
// readByXlsx(arr[i].fullPath);
}
}, 1000)
})
这段是在页面测试用代码,用了vue3的setup。下面展示一下控制台相关的打印。
这么一大段的字符串输出就是通过readAsDataURL获得的最初的字符串,可以看到最前面有一段供识别的base64识别码,必须删除,xlsx的base64识别会被这个影响(前面那段我理解的是给浏览器识别用的,因为base64图片也要用这种格式给浏览器写上去,不知道别的地方有没有这种写法)
然后看一下最终成功得到的数据