| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231 |
- const {
- getWxApi,
- isCancelError
- } = require('../utils/platform-utils.js')
- const {
- formatBytes
- } = require('../utils/binary-utils.js')
- function formatExportStamp(date = new Date()) {
- const pad = (value, length = 2) => String(value).padStart(length, '0')
- return [
- date.getFullYear(),
- pad(date.getMonth() + 1),
- pad(date.getDate()),
- '-',
- pad(date.getHours()),
- pad(date.getMinutes()),
- pad(date.getSeconds())
- ].join('')
- }
- function normalizeExtensions(extensions = []) {
- return extensions
- .map((extension) => String(extension || '').trim().replace(/^\./, '').toLowerCase())
- .filter(Boolean)
- }
- function getFileName(file, fallback = '未命名文件') {
- return String(file && file.name ? file.name : fallback)
- }
- function getFilePath(file) {
- return file && (file.path || file.tempFilePath) ? (file.path || file.tempFilePath) : ''
- }
- function getFirstSelectedFile(result, fallbackName = '未命名文件') {
- const file = result && Array.isArray(result.tempFiles) ? result.tempFiles[0] : null
- if (!file) throw new Error('没有选择文件')
- const filePath = getFilePath(file)
- if (!filePath) throw new Error('无法读取所选文件路径')
- return {
- file,
- name: getFileName(file, fallbackName),
- path: filePath
- }
- }
- function assertFileExtension(fileInfo, extensions = [], message = '文件格式不符') {
- const normalizedExtensions = normalizeExtensions(extensions)
- if (!normalizedExtensions.length) return
- const nameText = `${fileInfo && fileInfo.name ? fileInfo.name : ''} ${fileInfo && fileInfo.path ? fileInfo.path : ''}`
- const matched = normalizedExtensions.some((extension) => (
- new RegExp(`\\.${extension}$`, 'i').test(nameText)
- ))
- if (!matched) throw new Error(message)
- }
- function chooseMessageFile(options = {}) {
- const wxApi = getWxApi()
- const extensions = normalizeExtensions(options.extensions || options.extension || [])
- return new Promise((resolve, reject) => {
- if (typeof wxApi.chooseMessageFile !== 'function') {
- reject(new Error('当前微信版本不支持从聊天记录选择文件'))
- return
- }
- const chooseOptions = {
- count: options.count || 1,
- type: options.type || 'file',
- success: resolve,
- fail: reject
- }
- if (extensions.length) chooseOptions.extension = extensions
- wxApi.chooseMessageFile(chooseOptions)
- })
- }
- function chooseLocalFile(options = {}) {
- const wxApi = getWxApi()
- const extensions = normalizeExtensions(options.extensions || options.extension || [])
- return new Promise((resolve, reject) => {
- if (typeof wxApi.chooseFile !== 'function') {
- reject(new Error(options.unsupportedMessage || '当前微信版本不支持打开本地文件,请从聊天记录选择'))
- return
- }
- const chooseOptions = {
- count: options.count || 1,
- type: options.type || 'file',
- success: resolve,
- fail: reject
- }
- if (extensions.length) chooseOptions.extension = extensions
- wxApi.chooseFile(chooseOptions)
- })
- }
- function chooseFile(source = 'message', options = {}) {
- return source === 'local'
- ? chooseLocalFile(options)
- : chooseMessageFile(options)
- }
- function readFile(filePath, options = {}) {
- const wxApi = getWxApi()
- return new Promise((resolve, reject) => {
- if (typeof wxApi.getFileSystemManager !== 'function') {
- reject(new Error('当前微信版本不支持读取文件'))
- return
- }
- const fs = wxApi.getFileSystemManager()
- const readOptions = {
- filePath,
- success: (res) => resolve(res.data),
- fail: reject
- }
- if (options.encoding) readOptions.encoding = options.encoding
- fs.readFile(readOptions)
- })
- }
- function toUint8Array(data) {
- if (data instanceof Uint8Array) return data
- if (data instanceof ArrayBuffer) return new Uint8Array(data)
- if (ArrayBuffer.isView(data)) {
- return new Uint8Array(data.buffer, data.byteOffset, data.byteLength)
- }
- return new Uint8Array(data || new ArrayBuffer(0))
- }
- async function loadSelectedFile(source = 'message', options = {}) {
- const result = await chooseFile(source, options)
- const fileInfo = getFirstSelectedFile(result, options.fallbackName || '未命名文件')
- assertFileExtension(fileInfo, options.extensions || options.extension || [], options.extensionMessage || '文件格式不符')
- const data = await readFile(fileInfo.path, {
- encoding: options.encoding
- })
- const bytes = options.encoding ? null : toUint8Array(data)
- return {
- ...fileInfo,
- bytes,
- data,
- size: bytes ? bytes.length : String(data || '').length,
- sizeText: formatBytes(bytes ? bytes.length : String(data || '').length),
- text: options.encoding ? String(data || '') : ''
- }
- }
- function getUserDataFilePath(fileName) {
- const wxApi = getWxApi()
- const userDataPath = wxApi.env && wxApi.env.USER_DATA_PATH
- if (!userDataPath) throw new Error('当前微信版本不支持生成文件')
- return `${userDataPath}/${fileName}`
- }
- function writeTextFile(filePath, data, encoding = 'utf8') {
- const wxApi = getWxApi()
- if (typeof wxApi.getFileSystemManager !== 'function') {
- throw new Error('当前微信版本不支持生成文件')
- }
- const fs = wxApi.getFileSystemManager()
- if (typeof fs.writeFileSync !== 'function') {
- throw new Error('当前微信版本不支持同步生成文件')
- }
- fs.writeFileSync(filePath, data, encoding)
- }
- function shareFileToChat(filePath, fileName) {
- const wxApi = getWxApi()
- return new Promise((resolve, reject) => {
- if (typeof wxApi.shareFileMessage !== 'function') {
- reject(new Error('当前微信版本不支持发送文件到聊天'))
- return
- }
- wxApi.shareFileMessage({
- fileName,
- filePath,
- success: resolve,
- fail: reject
- })
- })
- }
- async function saveTextFileToChat(fileName, data) {
- const filePath = getUserDataFilePath(fileName)
- writeTextFile(filePath, data, 'utf8')
- await shareFileToChat(filePath, fileName)
- return filePath
- }
- module.exports = {
- assertFileExtension,
- chooseFile,
- chooseLocalFile,
- chooseMessageFile,
- formatBytes,
- formatExportStamp,
- getFirstSelectedFile,
- getUserDataFilePath,
- isCancelError,
- loadSelectedFile,
- readFile,
- saveTextFileToChat,
- shareFileToChat,
- toUint8Array,
- writeTextFile
- }
|