前言
最近公司需要开发微信小程序,使用的是uniapp来开发,然后有个功能需求需要用户将上传的excel文件提取出来并显示,于是我通过DeepSeek帮助引入了XLSX组件,发现上传超过了2M限制,就算分包也不成功,最后终于解决了,现在总结一下分享出来。
准备工作
操作步骤
刚开始我试了好多办法,如下所示:
方法一: xlsx.mini
// 单独引入,android是成功,但是ios有问题
import { read, utils } from 'xlsx/dist/xlsx.mini.min';
uploadExcelTemp() {
let toolResponses = [];
wx.chooseMessageFile({
count: 1, // 最多选择 1 个文件
type: 'file', // 关键:指定为普通文件类型
extension: ['.xlsx','xls'], // 限制文件类型为 .xlsx
success: async (res) => {
console.log('---chooseMessageFile success:', res)
const filePath = res.tempFiles[0].path;
try {
// 获取文件管理器
const fs = uni.getFileSystemManager();
// 读取文件数据 (Base64格式)
const fileData = await new Promise((resolve, reject) => {
fs.readFile({
filePath: filePath,
encoding: 'base64', // 重要!必须使用base64编码
success: res => resolve(res.data),
fail: reject
});
});
const arrayBuffer = uni.base64ToArrayBuffer(fileData); // 返回ArrayBuffer
// 如果需要字符串,转换ArrayBuffer为字符串
const binaryString = Array.from(new Uint8Array(arrayBuffer))
.map(byte => String.fromCharCode(byte))
.join('');
// 将Base64转换为二进制数据
// const binaryString = atob(fileData);
// 读取Excel工作簿
const workbook = XLSX.read(binaryString, {type: 'binary'});
// 获取第一个工作表
const firstSheetName = workbook.SheetNames[0];
const worksheet = workbook.Sheets[firstSheetName];
// 转换为JSON
const jsonData = XLSX.utils.sheet_to_json(worksheet);
console.log('转换后的JSON数据:', jsonData);
} catch (error) {
console.log('---chooseMessageFile error:', error)
}
},
fail: (err) => {
console.log('---chooseMessageFile err:', err)
}
});
},
结果:失败!android成功,ios失败
方法二:exceljs
// 1. 安装依赖(终端执行)
// npm install exceljs@4
// 2. 在页面/组件中实现
import ExcelJS from 'exceljs/dist/exceljs.min.js'; // 仅引入核心min版
export default {
methods: {
async chooseExcelFile() {
try {
// 选择文件
const [file] = await this.uniChooseFile();
console.log('选中文件:', file);
// 读取文件内容
const arrayBuffer = await this.readFile(file.path);
// 解析Excel
const jsonData = await this.parseExcel(arrayBuffer);
console.log('解析结果:', jsonData);
// 使用数据(示例:展示前5行)
this.excelData = jsonData.slice(0, 5);
} catch (error) {
console.error('处理失败:', error);
uni.showToast({ title: '文件处理失败', icon: 'none' });
}
},
// 封装文件选择
uniChooseFile() {
return new Promise((resolve, reject) => {
uni.chooseMessageFile({
count: 1,
type: 'file',
extension: ['.xlsx', '.xls'],
success: res => resolve(res.tempFiles),
fail: reject
});
});
},
// 封装文件读取
readFile(filePath) {
return new Promise((resolve, reject) => {
const fs = uni.getFileSystemManager();
fs.readFile({
filePath,
// 注意:小程序环境必须使用 arrayBuffer 格式
encoding: 'binary',
success: res => {
// 转换为 ArrayBuffer
const buffer = new Uint8Array(res.data.length);
for (let i = 0; i < res.data.length; i++) {
buffer[i] = res.data.charCodeAt(i) & 0xFF;
}
resolve(buffer);
},
fail: reject
});
});
},
// Excel解析核心方法
async parseExcel(arrayBuffer) {
const workbook = new ExcelJS.Workbook();
await workbook.xlsx.load(arrayBuffer);
const worksheet = workbook.getWorksheet(1); // 获取第一个工作表
if (!worksheet) throw new Error('工作表不存在');
const jsonData = [];
const headers = [];
// 提取表头(第一行)
worksheet.getRow(1).eachCell((cell, colIndex) => {
headers[colIndex] = cell.value?.toString() || `列${colIndex}`;
});
// 处理数据行(从第二行开始)
worksheet.eachRow((row, rowIndex) => {
if (rowIndex === 1) return; // 跳过表头
const rowData = {};
row.eachCell((cell, colIndex) => {
// 特殊处理日期格式
let value = cell.value;
if (cell.value instanceof Date) {
value = this.formatDate(cell.value);
}
rowData[headers[colIndex] = value?.toString() || '';
});
jsonData.push(rowData);
});
return jsonData;
},
// 日期格式化工具
formatDate(date) {
return `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')}`;
}
},
data() {
return {
excelData: [] // 存储解析结果
};
}
}
结果:失败!worksheet.eachRow这行,报:eachRow是undefined!
方法三:EXCEL转JSON函数
EXCEL转JSON函数 excel json
结果:失败!包也是太大了,跟引用xlsx没区别
方法四:云开发
结果:应该是可以的,不过需要收费!
方法五:uniapp发行压缩代码

点击运行:
16:58:07.734 正在编译中...
16:58:24.208 项目 编译成功。前端运行日志,请另行在小程序开发工具的控制台查看。
16:58:24.208 正在启动微信开发者工具...
16:58:24.479 [微信小程序开发者工具] - initialize
16:58:24.482 [微信小程序开发者工具] ✖ IDE may already started at port 21765, trying to connect
16:58:26.403 [微信小程序开发者工具] ✔ IDE server started successfully, listening on http://127.0.0.1:32739
16:58:26.409 [微信小程序开发者工具] - open IDE
16:58:27.716 [微信小程序开发者工具] ✔ open IDE
16:58:27.736 微信开发者工具已启动,在HBuilderX中修改文件并保存,会自动刷新微信模拟器。
16:58:27.736 注:
16:58:27.736 1. 可以通过微信开发者工具切换pages.json中condition配置的页面,或者关闭微信开发者工具,然后再从HBuilderX中启动指定页面
16:58:27.736 2. 如果出现微信开发者工具启动后白屏的问题,检查是否启动多个微信开发者工具,如果是则关闭所有打开的微信开发者工具,然后再重新运行
16:58:27.736 3. 运行模式下不压缩代码且含有sourcemap,体积较大;若要正式发布,请点击发行菜单进行发布
16:58:27.736 运行方式:打开 微信开发者工具, 导入 dist/dev/mp-weixin 运行。
点击发行:
[HBuilder] 17:03:17.129 项目 [__UNI__40FC4BC] 开始发布到微信小程序...
[HBuilder] 17:03:18.334 小程序各家浏览器内核及自定义组件实现机制存在差异,可能存在样式布局兼容问题,参考:https://uniapp.dcloud.io/matter?id=mp
[HBuilder] 17:03:18.338 正在编译中...
[HBuilder] 17:03:42.492 项目 编译成功。前端运行日志,请另行在小程序开发工具的控制台查看。
[HBuilder] 17:03:42.542 项目 导出微信小程序成功,路径为:
[HBuilder] 17:03:42.544 正在启动微信开发者工具...
[HBuilder] 17:03:42.819 [微信小程序开发者工具] - initialize
[HBuilder] 17:03:42.836 [微信小程序开发者工具] ✔ IDE server has started, listening on http://127.0.0.1:32739
[HBuilder] 17:03:42.837 [微信小程序开发者工具] - open IDE
[HBuilder] 17:03:43.615 [微信小程序开发者工具] ✔ open IDE
[HBuilder] 17:03:43.620 请在微信小程序开发者工具中点击上传
然后在微信开发者工具点击上传即可!
结果:成功解决!我的理解是发行相当于build,不会把.sourcemap等文件打包,这样上传的时候代码体积就变小点!
注意:发行操作必须登录uniapp账号,顺便说一句,要保持manifest.json中的APPID一致,如果不一致,点击右侧重新获取一下即可

问题
1、atob is not defined
const binaryString = atob(fileData);
报错:atob is not defined
解决:使用uni-app自带的Base64转换API
const arrayBuffer = uni.base64ToArrayBuffer(fileData); // 返回ArrayBuffer
// 如果需要字符串,转换ArrayBuffer为字符串
const binaryString = Array.from(new Uint8Array(arrayBuffer))
.map(byte => String.fromCharCode(byte))
.join('');
2、uni.chooseFile微信端不支持,使用wx.chooseMessageFile
解决:

总结
1、引用大包时要么分包,要么使用uniapp的发行压缩代码再上传,还有就是引用云函数!
1万+






