文件存储最基础的两个字段是文件内容和文件名称,在数据中FileContent的数据类型为varbinary(max) (这种方式的弊端是不能大量存储文件,会占用数据库的大量内存)
现在将文件通过文件的完整路径,获取文件的二进制流和文件名(包含后缀)
filePath是文件的完整路径
byte[] FileData = File.ReadAllBytes(filePath);
// 获取文件名(带扩展名)
string fileNameWithExtension = Path.GetFileName(filePath);
然后使用参数化的方式将byte[]类型数据存入数据库中
现在我们将文件从数据库中读出来
取出文件内容的核心代码逻辑是把取出的二进制数据转为base64类型字符,并取出文件名字(文件的基本信息存储在以下类中)
微信小程序中页面效果图如下:(暂时只包含了文件名称和下载文件的操作)
<!-- 新增文件下载栏 --> <view class="file-download-section"> <!-- 文件图标占位(根据文件类型显示不同图标) --> <view class="file-icon {{fileTypeClass}}"> <text class="file-icon-text">{{fileIcon}}</text> </view> <view class="file-info"> <view class="file-name">{{fileName || '未命名文件'}}</view> </view> <button class="download-btn" bindtap="handleDownload"> <text class="download-btn-text">{{isDownloading ? '下载中...' : '下载文件'}}</text> </button> </view>
/* 文件下载栏样式 */ .file-download-section { display: flex; align-items: center; padding: 24rpx 30rpx; background-color: #ffffff; border-radius: 12rpx; box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05); margin-bottom: 30rpx; } /* 文件图标样式 */ .file-icon { width: 80rpx; height: 80rpx; border-radius: 8rpx; background-color: #f0f0f0; display: flex; align-items: center; justify-content: center; margin-right: 20rpx; font-size: 40rpx; } /* 不同文件类型的图标样式 */ .file-icon.pdf { background-color: #e6f7ff; color: #1890ff; } .file-icon.doc { background-color: #f6ffed; color: #52c41a; } .file-icon.jpg, .file-icon.png { background-color: #fff3e0; color: #fa8c16; } .file-icon.zip { background-color: #fce8e6; color: #ff4d4f; } /* 文件信息区域样式 */ .file-info { flex: 1; min-width: 0; margin-right: 20rpx; } .file-name { font-size: 28rpx; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-bottom: 6rpx; } .file-size { font-size: 24rpx; color: #999; } /* 下载按钮样式 */ .download-btn { min-width: 160rpx; height: 70rpx; line-height: 70rpx; padding: 0; background-color: #1890ff; color: #ffffff; border-radius: 35rpx; font-size: 28rpx; } .download-btn-text { display: block; }
接下来需要js文件将base64字符转为可使用的本地文件缓存地址
// Base64 解码实现 (替代浏览器的 atob) function atob(base64) { // Base64 字符表 const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; // 移除空格并验证长度 base64 = base64.replace(/\s/g, ''); if (base64.length % 4 !== 0) { throw new Error('Invalid base64 string'); } let output = ''; let i = 0; // 解码逻辑 while (i < base64.length) { const enc1 = chars.indexOf(base64.charAt(i++)); const enc2 = chars.indexOf(base64.charAt(i++)); const enc3 = chars.indexOf(base64.charAt(i++)); const enc4 = chars.indexOf(base64.charAt(i++)); const chr1 = (enc1 << 2) | (enc2 >> 4); const chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); const chr3 = ((enc3 & 3) << 6) | enc4; output += String.fromCharCode(chr1); if (enc3 !== 64) { output += String.fromCharCode(chr2); } if (enc4 !== 64) { output += String.fromCharCode(chr3); } } return output; } function base64ToArrayBuffer(base64) { const base64Str = base64.replace(/^data:image\/\w+;base64,/, ''); const binary = atob(base64Str); const len = binary.length; const buffer = new ArrayBuffer(len); const view = new Uint8Array(buffer); for (let i = 0; i < len; i++) { view[i] = binary.charCodeAt(i); } return buffer; } function downloadBase64File(base64Str, fileName) { return new Promise((resolve, reject) => { try { const buffer = base64ToArrayBuffer(base64Str); const fs = wx.getFileSystemManager(); const tempFilePath = `${wx.env.USER_DATA_PATH}/${fileName || 'download_' + Date.now()}`; console.log(tempFilePath) fs.writeFile({ filePath: tempFilePath, data: buffer, success: () => { wx.getFileSystemManager().saveFile({ tempFilePath: tempFilePath, success: (res) => resolve(res.savedFilePath), fail: (err) => reject(err) }); }, fail: (err) => reject(err) }); } catch (error) { reject(error); } }); } export { downloadBase64File };
在这里我们需要将这个文件新建到util文件下
在微信小程序中通过接口请求后获取到以上的文件信息
最后实现方法(以上参数中的DocumentContent、FileName分别赋值给data中的fileContent、fileName)
下载文件核心代码:
getBase64FromServer(){ return this.data.fileContent; }, handleDownload() { const base64Data = this.getBase64FromServer(); this.downloadFile(base64Data, this.data.fileName); }, ///下载文件(逻辑代码) downloadFile(base64Str, fileName) { wx.showLoading({ title: '下载中...' }); downloadBase64File(base64Str, fileName) .then(savedFilePath => { console.log("缓存成功路径:" + savedFilePath) // 打开文件供用户保存 wx.openDocument({ filePath: savedFilePath, showMenu: true, success: () => { wx.showToast({ title: '下载成功', }) }, fail: (err) => { wx.showToast({ title: '打开文件失败', icon: 'none' }); console.error(err); } }); wx.hideLoading(); }) .catch(err => { wx.hideLoading(); wx.showToast({ title: '保存失败', icon: 'none' }); console.error('下载错误:', err); }); },
最后测试点击下载文件按钮可以预览文件
可以点击右上角三个点选择下载到手机上(可以手机的文件管理的文档中找到)