当前位置: 首页 > news >正文

小程序文件在线显示(支持word,图片,视频等)

小程序文件在线显示(支持word,图片,视频等)

  • 一、介绍
  • 二、代码
    • vue代码
    • word图标
    • video图标
    • txt图标
    • ppt图标
    • pdf图标
    • image图标
    • file图标
    • excel图标

一、介绍

又是一天敲代码,今天公司要求一个文件上传,可以传多个类型的文件,而且在小程序还都要在线给他显示出来(之前明明就要求显示一个pdf就可以了)现在给我整这出,我真的XXX。

下班点到了,就先凑合一写,后续在进行优化。

二、代码

这里的代码不是俺写的,实在原来显示pdf的基础上加入了word,excel,图片视频等。
具体文件,我这边使用图标进行区分了一下(图片我上传到服务器了,这里使用的是svg代码也会贴在下面,方便使用),点击去具体的文件都可以进行显示,点击word之类的就会跳转打开,图片视频文本会弹窗显示。
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

vue代码

<template><view style="background-color: #FFF;padding-bottom: 200rpx;"><cu-custom bgColor="bg-gradual-blue" :isBack="true"><block slot="backText">返回</block><block slot="content">文件明细</block></cu-custom><!-- 加载组件 --><view class="loading-container" v-if="loading"><u-loading-icon color="red" size="40"></u-loading-icon></view><!-- 视频组件 --><view v-if="showVideo" class="video-modal"><view class="modal-mask" @click="closeVideo"></view><view class="video-container"><view class="close-btn" @click="closeVideo">×</view><video id="videoPlayer" :src="videoUrl" :controls="true" :autoplay="true" class="video-player"@error="handleVideoError"></video></view></view><!-- 文本组件 --><view v-if="showTxt" class="txt-modal"><view class="modal-mask" @click="closeTxt"></view><view class="txt-container"><view class="close-btn" @click="closeTxt">×</view><view class="txt-title">{{currentTxtName}}</view><view class="txt-content"><view class="txt-content-text">{{txtContent}}</view></view></view></view><view class="file-info-item"style="margin-top: 30rpx;border-bottom: 1rpx solid #cac7c7;padding-top: 15rpx;padding: 0rpx 40rpx  0rpx  40rpx;"><view class="" style="color: #9e9898;">标题:</view><view style="padding-top: 15rpx;font-size: 30rpx; font-weight: bold;margin-bottom: 25rpx;">{{dataInfo.title}}</view></view><view class="file-info-item"style="margin-top: 30rpx;border-bottom: 1rpx solid #cac7c7; padding: 0rpx 40rpx  0rpx  40rpx;"><view class="" style="color: #9e9898;">发送人:</view><view style="padding-top: 15rpx;font-size: 30rpx; margin-bottom: 25rpx;">{{dataInfo.createByName}}</view></view><view class="file-info-item"style="margin-top: 30rpx;border-bottom: 1rpx solid #cac7c7;padding: 0rpx 40rpx  0rpx  40rpx;"><view class="" style="color: #9e9898;">发送时间:</view><view style="padding-top: 15rpx;font-size: 30rpx;margin-bottom: 25rpx;">{{dataInfo.createTime}}</view></view><view class="file-info-item"style="margin-top: 30rpx;border-bottom: 1rpx solid #cac7c7; padding: 0rpx 40rpx  0rpx  40rpx;"><view class="" style="color: #9e9898;">附件文件:</view><view v-for="(item, index) in fileList" :key="index"><view @click="openFile(item.url)"><view style="margin-top:15rpx;margin-bottom: 25rpx;display: flex;" class="fileClass"><view><img :src="getFileIcon(item.url)" alt="" style="width: 80rpx;height: 80rpx;"></view><view style="margin-top: 20rpx;margin-left: 15rpx;"><text style="color: #2e61d7;">{{ item.fileName }}</text></view></view></view></view></view><view class="file-info-item" style="margin-top: 30rpx; padding: 0rpx 40rpx  0rpx  40rpx;"><view class="" style="color: #9e9898;">内容:</view><view style="margin-top: 20rpx;width: 90%;margin-left: 5%;"><!-- <rich-text :nodes="dataInfo.content"></rich-text> --><u-parse :content="dataInfo.content"></u-parse></view></view></view>
</template><script>import configService from '@/common/service/config.service.js';import {ACCESS_TOKEN} from "@/common/util/constants"export default {data() {return {fileType: '', // 文件类型basUrl: configService.apiUrl + '/',loading: false,fileList: [],id: '',dataInfo: {title: '',createByName: '',createTime: '',content: '',},showVideo: false,videoUrl: '',videoContext: null, // 视频上下文对象showTxt: false, // TXT弹窗显示开关currentTxtName: '', // 当前预览的TXT文件名txtContent: '', // TXT文件内容};},onReady() {this.videoContext = uni.createVideoContext('videoPlayer', this);},mounted() {},onLoad(e) {this.id = e.idthis.getFileById()},onShow() {// 在这里进行页面重新显示到屏幕上时的操作this.loading = false},methods: {// 打开文件openFile(fileUrl) {this.loading = true;// 文件地址const fullUrl = this.basUrl + fileUrl;// 获取文件类型信息const {fileName,fileExt,isImage,isVideo,isDoc} = this.checkFileType(fileUrl);uni.downloadFile({url: fullUrl, // 文件下载地址header: {'X-Access-Token': uni.getStorageSync(ACCESS_TOKEN)},success: response => {if (response.statusCode !== 200) {uni.showToast({title: '文件下载失败',icon: 'none'});return;}const tempFilePath = response.tempFilePath;// 图片文件if (isImage) {this.previewImage(tempFilePath)}// 视频文件else if (isVideo) {this.playVideo(tempFilePath);}// 文档文件else if (isDoc) {fileExt === '.txt' ?this.previewTxt(tempFilePath, fileName) :this.openDocument(tempFilePath, fileExt);} else {uni.showToast({title: `不支持${fileExt}格式`,icon: 'none'});}},fail: downloadError => {this.loading = falseuni.showToast({title: '下载失败,请检查网络',icon: 'none'});}})},// 图片previewImage(tempFilePath) {uni.previewImage({current: tempFilePath,urls: [tempFilePath],fail: imgError => {console.log('图片预览失败:', imgError);uni.showToast({title: '图片预览失败',icon: 'none'});}});},// 视频playVideo(tempFilePath) {this.showVideo = true;this.videoUrl = tempFilePath;// 用$nextTick替代setTimeout,确保DOM渲染完成后再初始化上下文this.$nextTick(() => {this.videoContext = uni.createVideoContext('videoPlayer', this);});},// TXTpreviewTxt(tempFilePath, fileName) {this.loading = false; // 关闭全局加载this.showTxt = true; // 显示TXT弹窗this.currentTxtName = fileName; // 显示文件名// 微信小程序API:读取本地临时文件内容(TXT为文本格式,用utf-8编码)const fs = uni.getFileSystemManager();try {const content = fs.readFileSync(tempFilePath, 'utf-8');// 读取成功:赋值内容,关闭加载this.txtContent = content;this.txtLoading = false;} catch (err) {// 3. 完整捕获错误:提示用户,关闭加载console.error('TXT读取失败:', err);this.txtContent = '文本读取失败,请重试';this.txtLoading = false;// 额外提示用户错误原因uni.showToast({title: '文本读取失败',icon: 'none'});}},// 文档openDocument(tempFilePath, fileExt) {uni.saveFile({tempFilePath: tempFilePath,success: (resData) => {uni.openDocument({filePath: resData.savedFilePath,fileType: this.getFileType(fileExt),showMenu: true, // 允许出现分享功能success: r => {this.loading = false;uni.showToast({title: '正在打开文件',icon: 'none',duration: 1500});},fail: (openError) => {this.loading = falseconsole.error('文档打开失败:', openError);const errorMsg = openError.errMsg.includes('not support') ?'不支持该文件格式' : openError.errMsg.includes('not found') ?'文件不存在或已损坏' :'文件打开失败,请重试';uni.showToast({title: errorMsg,icon: 'none'});}})},fail: (error) => {this.loading = false;console.error('文件保存失败:', error);uni.showToast({title: '文件保存失败,请重试',icon: 'none'});}})},// 判断文件图标getFileIcon(fileUrl) {// 提取文件后缀(兼容URL带参数的情况)const fileName = decodeURIComponent(fileUrl.split('/').pop().split('?')[0]);const lastDotIndex = fileName.lastIndexOf('.');const fileExt = lastDotIndex > -1 ? fileName.substring(lastDotIndex).toLowerCase() : '';// 定义文件类型与图标映射const iconMap = {// 图片类型'.png': this.basUrl + '/svg/image.svg','.jpg': this.basUrl + '/svg/image.svg','.jpeg': this.basUrl + '/svg/image.svg','.gif': this.basUrl + '/svg/image.svg',// 视频类型'.mp4': this.basUrl + '/svg/video.svg','.mov': this.basUrl + '/svg/video.svg','.avi': this.basUrl + '/svg/video.svg',// 文档类型'.doc': this.basUrl + '/svg/word.svg','.docx': this.basUrl + '/svg/word.svg','.xls': this.basUrl + '/svg/excel.svg','.xlsx': this.basUrl + '/svg/excel.svg','.csv': this.basUrl + '/svg/excel.svg','.pdf': this.basUrl + '/svg/pdf.svg','.txt': this.basUrl + '/svg/txt.svg','.ppt': this.basUrl + '/svg/ppt.svg','.pptx': this.basUrl + '/svg/ppt.svg'};// 返回对应图标,默认用通用文件图标return iconMap[fileExt] || this.basUrl + '/svg/file.svg';},// 判断文档类型getFileType(fileType) {const extMap = {'.doc': 'doc','.docx': 'doc','.ppt': 'ppt','.pptx': 'ppt','.xls': 'xls','.xlsx': 'xls','.csv': 'xls','.pdf': 'pdf','.txt': 'txt'};return extMap[fileType] || '';},// 检查文件类型checkFileType(fileUrl) {// 提取文件名和后缀(兼容URL中含参数的场景,如 "file.pdf?id=123")const fileName = decodeURIComponent(fileUrl.split('/').pop().split('?')[0]);const lastDotIndex = fileName.lastIndexOf('.');const fileExt = lastDotIndex > -1 ? fileName.substring(lastDotIndex).toLowerCase() : '';// 定义支持的文件类型集合const imageExts = ['.png', '.jpg', '.jpeg', '.gif', '.bmp'];const videoExts = ['.mp4', '.webm', '.mov', '.avi', '.mkv'];const docExts = ['.doc', '.docx', '.ppt', '.pptx', '.xls', '.xlsx', '.csv', '.pdf', '.txt'];return {fileName: fileName, // 纯净文件名(不含URL参数)fileExt: fileExt, // 小写文件后缀isImage: imageExts.includes(fileExt),isVideo: videoExts.includes(fileExt),isDoc: docExts.includes(fileExt)};},// 根据id查询数据getFileById() {this.$http.get('/hisonline/basUploadFile/list', {params: {mainId: this.id}}).then(data => {this.fileList = data.data.result.records})this.$http.get('/safety/homeAnnouncement/queryById', {params: {id: this.id}}).then(res => {this.dataInfo = res.data.resultconsole.log(this.dataInfo, "渲染进本信息");});},// 关闭视频closeVideo() {this.loading = falsethis.showVideo = false;this.videoUrl = '';// 停止播放并释放资源if (this.videoContext) {this.videoContext.stop();this.videoContext = null;}},// 视频播放错误处理handleVideoError(err) {console.error('视频播放错误:', err);uni.showToast({title: '视频加载失败,请重试',icon: 'none',duration: 2000});this.closeVideo(); // 错误时关闭弹窗},// 关闭TXT弹窗closeTxt() {this.showTxt = false;this.txtContent = ''; // 清空内容,避免下次复用},},}
</script><style lang="scss" scoped>.fileClass {overflow: hidden;white-space: nowrap;text-overflow: ellipsis;}// 视频弹窗遮罩.video-modal {position: fixed;top: 0;left: 0;right: 0;bottom: 0;z-index: 9999; // 确保在最上层display: flex;justify-content: center;align-items: center;}// 半透明背景.modal-mask {position: absolute;top: 0;left: 0;right: 0;bottom: 0;background-color: rgba(0, 0, 0, 0.8); // 深色半透明,突出视频}// 视频容器.video-container {width: 90%;max-width: 800rpx;min-height: 400rpx;}// 视频播放器.video-player {width: 100%;background-color: #000; // 黑色背景更适合视频border-radius: 12rpx; // 圆角更美观object-fit: contain;}// 关闭按钮.close-btn {position: absolute;top: -60rpx;right: 0;width: 50rpx;height: 50rpx;color: #fff;font-size: 50rpx;text-align: center;background-color: rgba(0, 0, 0, 0.5);border-radius: 50%;line-height: 45rpx;}// 全局加载组件样式.loading-container {position: fixed;top: 0;left: 0;right: 0;bottom: 0;display: flex;justify-content: center;align-items: center;z-index: 999; // 确保覆盖其他内容background-color: rgba(255, 255, 255, 0.5); // 半透明背景,提示正在加载}// 视频弹窗样式.txt-modal {position: fixed;top: 0;left: 0;right: 0;bottom: 0;z-index: 9999;display: flex;justify-content: center;align-items: center;}.txt-container {width: 90%;max-width: 700rpx;max-height: 70vh; // 限制弹窗最大高度为屏幕70%,避免超出屏幕background-color: #FFFFFF;border-radius: 12rpx;padding: 30rpx;position: relative;z-index: 2;overflow: hidden; // 防止内部内容溢出弹窗}.txt-title {font-size: 28rpx;font-weight: bold;color: #333333;margin-bottom: 20rpx;padding-bottom: 15rpx;border-bottom: 1rpx solid #EEEEEE;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;}.txt-content {width: 100%;height: calc(100% - 60rpx); // 减去标题高度,确保内容区不被挤压max-height: 60vh; // 限制内容区最大高度overflow-y: auto; // 内容超出时显示垂直滚动条font-size: 24rpx;color: #666666;line-height: 40rpx;padding-right: 10rpx; // 避免文字与滚动条重叠}.txt-content-text {white-space: pre-wrap; // 保留换行(\n)和空格word-break: break-all; // 长单词/长数字强制换行,避免横向溢出line-height: 48rpx; // 适当增加行高,提升可读性}
</style>

word图标

<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg"><rect x="3" y="6" width="34" height="28" rx="2" stroke="#2196F3" stroke-width="2" fill="white"/><text x="12.5" y="27" font-family="Arial, sans-serif" font-size="18" font-weight="bold" fill="#2196F3">W</text>
</svg>

video图标

<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg"><rect x="3" y="6" width="34" height="28" rx="2" stroke="#F44336" stroke-width="2" fill="white"/><polygon points="17,14 27,20 17,26" fill="#F44336"/>
</svg>

txt图标

<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg"><rect x="3" y="6" width="34" height="28" rx="2" stroke="#9E9E9E" stroke-width="2" fill="white"/><line x1="12" y1="16" x2="28" y2="16" stroke="#9E9E9E" stroke-width="2"/><line x1="12" y1="21" x2="25" y2="21" stroke="#9E9E9E" stroke-width="2"/><line x1="12" y1="26" x2="22" y2="26" stroke="#9E9E9E" stroke-width="2"/>
</svg>

ppt图标

<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg"><rect x="3" y="6" width="34" height="28" rx="2" stroke="#FF9800" stroke-width="2" fill="white"/><text x="6.5" y="26" font-family="Arial, sans-serif" font-size="14" font-weight="bold" fill="#FF9800">PPT</text>
</svg>

pdf图标

<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg"><rect x="3" y="6" width="34" height="28" rx="2" stroke="#F44336" stroke-width="2" fill="white"/><text x="8" y="26" font-family="Arial, sans-serif" font-size="14" font-weight="bold" fill="#F44336">PDF</text>
</svg>

image图标

<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg"><rect x="3" y="6" width="34" height="28" rx="2" stroke="#9C27B0" stroke-width="2" fill="white"/><text x="8" y="26" font-family="Arial, sans-serif" font-size="14" font-weight="bold" fill="#9C27B0">PIC</text>
</svg>

file图标

<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg"><rect x="3" y="6" width="34" height="28" rx="2" stroke="#3F51B5" stroke-width="2" fill="white"/><text x="9" y="26" font-family="Arial, sans-serif" font-size="14" font-weight="bold" fill="#3F51B5">File</text>
</svg>

excel图标

<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg"><rect x="3" y="6" width="34" height="28" rx="2" stroke="#1976D2" stroke-width="2" fill="white"/><text x="15" y="26" font-family="Arial, sans-serif" font-size="18" font-weight="bold" fill="#1976D2">E</text>
</svg>
http://www.dtcms.com/a/524143.html

相关文章:

  • 记录自己写项目的第三天,springbot+redis+rabbitma高并发项目
  • Linux下查看系统启动时间、运行时间
  • Linux中子系统注册subsystem_register等函数的实现
  • MFC应用程序,工作线程学习记录
  • 在什么网站做公司人员增减wordpress主题标签
  • 广州新塘网站制作推广网站服务器检测
  • 金仓多模数据库:电子证照系统国产化替代MongoDB的优选方案
  • SQL之键与约束——数据库设计的基石与数据完整性的守护者
  • 百度网站收录查询地址保定网站推广多少钱
  • 移动端网站如何开发一呼百应网
  • Spring Boot集合RabbitMQ
  • 傻瓜式大型网站开发工具金融 网站 源码
  • 精准与安全并重!NHVOC-1 (C) 型便携式 VOCs 分析仪(PID + 催化氧化 - NDIR)深度解析
  • WPF ComboBox 样式
  • paddlenlp 3.x 版本使用uie-m-base报错找不到 static/inference.pdmodel
  • 郑州市有做网站的吗wordpress如何设置点击直接下载
  • 深度学习打卡第TR5周:Transformer实战:文本分类
  • 一个强大的开源OCR工具,基于DeepSeek OCR
  • 【AI工具】Lyra超级元提示词原文分享:颠覆AI交互逻辑的「提问式」优化工具
  • 企业级表单与文件上传统一管理方案
  • 报错解决:IEEE latex模版中thanks不显示 隶属关系 / 邮箱不显示
  • 第四章:向量数据库:解锁Embeddings价值的钥匙
  • 微信的微网站模板下载wordpress 后台502
  • 基于JavaWeb技术的在线考试系统设计与实现
  • Function Calling VS MCP
  • 找公司网站建设销售网页
  • C++仿muduo库高并发服务器项目:Channel模块
  • 网站开发前端php 后端python张家界seo
  • [特殊字符]兰亭妙微审美积累|总结三个情感化设计细节✨
  • 【数列求和】