专门做尿不湿的网站,科技小发明图片,自媒体wordpress主题分享,做网站要sql 数据库名字账号密码小程序附件上传的文件类型限制问题 问题背景 在小程序开发中#xff0c;附件上传是常见功能。但很多开发者在实现时会遇到一个问题#xff1a;用户只能选择图片#xff0c;无法选择PDF、Word等其他类型的文件。 最近在开发审批功能时就遇到了这个问题#x…小程序附件上传的文件类型限制问题问题背景在小程序开发中附件上传是常见功能。但很多开发者在实现时会遇到一个问题用户只能选择图片无法选择PDF、Word等其他类型的文件。最近在开发审批功能时就遇到了这个问题审批申请需要上传附件如合同、发票等但用户反馈只能选择图片无法选择其他文件。问题现象期望效果 ┌─────────────────────────────────────┐ │ 添加附件 │ │ [图片] [PDF] [Word] [Excel] ... │ └─────────────────────────────────────┘ 实际效果 ┌─────────────────────────────────────┐ │ 添加附件 │ │ [图片] [图片] [图片] 只能选图片 │ └─────────────────────────────────────┘问题根因小程序文件选择 API 对比小程序提供了多个文件选择 API各有不同的用途和限制API用途支持的文件类型平台支持uni.chooseImage()选择图片仅图片jpg/png/gif等全平台uni.chooseVideo()选择视频仅视频mp4等全平台uni.chooseFile()选择文件多种文件类型H5/App小程序不支持uni.chooseMessageFile()从聊天记录选择多种文件类型仅微信小程序问题代码// 错误写法只能选择图片constchooseFile(){uni.chooseImage({count:9,success:(res){// 只能获取到图片uploadFiles(res.tempFilePaths)}})}问题在于使用了chooseImage这个 API 顾名思义只能选择图片。解决方案方案一使用 chooseMessageFile微信小程序推荐微信小程序专属 API允许用户从微信聊天记录中选择文件constchooseFile(){uni.chooseMessageFile({count:9,type:file,// all | image | video | filesuccess:(res){// res.tempFiles 包含文件信息// [{ path, size, name, type }]constfilesres.tempFiles.map(file({path:file.path,name:file.name,size:file.size,type:file.type}))uploadFiles(files)}})}优点支持选择各种文件类型PDF、Word、Excel等用户可以从聊天记录快速选择已有文件体验流畅符合微信用户习惯缺点仅微信小程序支持文件必须存在于聊天记录中方案二组合多个 API提供多种选择入口满足不同需求template view classupload-section view classupload-title添加附件/view view classupload-buttons button clickchooseImage选择图片/button button clickchooseFromChat从聊天记录选择/button /view !-- 已选文件列表 -- view classfile-list view v-for(file, index) in fileList :keyindex classfile-item image v-ifisImage(file) :srcfile.path classfile-thumb / view v-else classfile-icon {{ getFileIcon(file.name) }} /view text classfile-name{{ file.name }}/text text classfile-delete clickremoveFile(index)删除/text /view /view /view /template script setup import { ref } from vue const fileList ref([]) // 选择图片 const chooseImage () { uni.chooseImage({ count: 9 - fileList.value.length, success: (res) { const newFiles res.tempFilePaths.map((path, index) ({ path, name: 图片${fileList.value.length index 1}.jpg, type: image })) fileList.value.push(...newFiles) } }) } // 从聊天记录选择微信小程序 const chooseFromChat () { // #ifdef MP-WEIXIN uni.chooseMessageFile({ count: 9 - fileList.value.length, type: file, success: (res) { const newFiles res.tempFiles.map(file ({ path: file.path, name: file.name, size: file.size, type: getFileType(file.name) })) fileList.value.push(...newFiles) } }) // #endif // #ifndef MP-WEIXIN uni.showToast({ title: 当前平台不支持, icon: none }) // #endif } // 判断是否为图片 const isImage (file) { return file.type image || /\.(jpg|jpeg|png|gif|webp)$/i.test(file.name) } // 获取文件图标 const getFileIcon (fileName) { const ext fileName.split(.).pop().toLowerCase() const iconMap { pdf: , doc: , docx: , xls: , xlsx: , ppt: ️, pptx: ️, zip: , rar: } return iconMap[ext] || } // 获取文件类型 const getFileType (fileName) { if (/\.(jpg|jpeg|png|gif|webp)$/i.test(fileName)) return image if (/\.(mp4|mov|avi)$/i.test(fileName)) return video return file } // 删除文件 const removeFile (index) { fileList.value.splice(index, 1) } /script方案三跨平台兼容封装封装一个通用的文件选择函数自动适配不同平台// utils/chooseFile.js/** * 跨平台文件选择 * param {Object} options * param {number} options.count - 最大选择数量 * param {string} options.type - 文件类型all | image | video | file * returns {PromiseArray} 文件列表 */exportconstchooseFile(options{}){const{count9,typeall}optionsreturnnewPromise((resolve,reject){// 微信小程序使用 chooseMessageFile// #ifdef MP-WEIXINif(typeimage){uni.chooseImage({count,success:(res){resolve(res.tempFilePaths.map((path,i)({path,name:image_${Date.now()}_${i}.jpg,type:image})))},fail:reject})}else{uni.chooseMessageFile({count,type:typeall?all:type,success:(res){resolve(res.tempFiles.map(file({path:file.path,name:file.name,size:file.size,type:file.type})))},fail:reject})}// #endif// H5/App使用 chooseFile// #ifdef H5 || APP-PLUSuni.chooseFile({count,type:typeall?all:type,success:(res){resolve(res.tempFiles.map(file({path:file.path,name:file.name,size:file.size,type:file.type})))},fail:reject})// #endif})}使用方式import{chooseFile}from/utils/chooseFile// 选择任意文件constfilesawaitchooseFile({count:5,type:all})// 只选择图片constimagesawaitchooseFile({count:9,type:image})文件上传的完整流程选择文件后还需要上传到服务器/** * 上传文件到服务器 * param {Array} files - 文件列表 * returns {PromiseArray} 上传结果 */exportconstuploadFilesasync(files){constuploadTasksfiles.map(file{returnnewPromise((resolve,reject){uni.uploadFile({url:https://api.example.com/upload,filePath:file.path,name:file,formData:{fileName:file.name,fileType:file.type},success:(res){constdataJSON.parse(res.data)resolve({...file,url:data.url,// 服务器返回的文件URLid:data.id})},fail:reject})})})returnPromise.all(uploadTasks)}注意事项1. 文件大小限制小程序对上传文件大小有限制建议在选择后进行校验constMAX_FILE_SIZE10*1024*1024// 10MBconstvalidateFileSize(files){constoversizedFilesfiles.filter(ff.sizeMAX_FILE_SIZE)if(oversizedFiles.length0){uni.showToast({title:文件大小不能超过10MB,icon:none})returnfalse}returntrue}2. 文件类型校验防止用户上传不支持的文件类型constALLOWED_EXTENSIONS[jpg,jpeg,png,gif,pdf,doc,docx,xls,xlsx]constvalidateFileType(files){constinvalidFilesfiles.filter(f{constextf.name.split(.).pop().toLowerCase()return!ALLOWED_EXTENSIONS.includes(ext)})if(invalidFiles.length0){uni.showToast({title:不支持的文件类型,icon:none})returnfalse}returntrue}3. 用户体验优化显示上传进度支持取消上传上传失败自动重试constuploadWithProgress(file,onProgress){returnnewPromise((resolve,reject){consttaskuni.uploadFile({url:https://api.example.com/upload,filePath:file.path,name:file,success:(res)resolve(JSON.parse(res.data)),fail:reject})// 监听上传进度task.onProgressUpdate((res){onProgressonProgress(res.progress)})})}总结API 选择很重要chooseImage只能选图片需要选择其他文件类型时应使用chooseMessageFile微信或chooseFileH5/App平台差异需处理不同平台支持的 API 不同建议封装统一的文件选择函数完善的校验机制文件大小、文件类型都需要校验避免上传失败或服务器压力良好的用户体验提供多种选择方式、显示上传进度、处理异常情况本文源于实际项目中的问题修复经验希望对遇到类似问题的开发者有所帮助。