修正上传文件名

This commit is contained in:
zhonghua.li
2026-04-19 15:34:16 +08:00
parent f05a85bc1c
commit 15c554a7c2
6 changed files with 93 additions and 8 deletions

View File

@@ -3,6 +3,6 @@
* apiEnv 可选:'local' | 'prod' * apiEnv 可选:'local' | 'prod'
*/ */
export default { export default {
apiEnv: 'prod' apiEnv: 'local'
} }

View File

@@ -401,7 +401,7 @@ export default {
this.stopRecordingTicker(); this.stopRecordingTicker();
const tempFilePath = res.tempFilePath || ''; const tempFilePath = res.tempFilePath || '';
if (ctx && ctx.id) { if (ctx && ctx.id) {
const name = `service_record_${ctx.id}_${Date.now()}_part${normalizedSegmentNo}.mp3`; const name = this.getAudioUploadFileName({ segmentNo: normalizedSegmentNo });
if (!tempFilePath) { if (!tempFilePath) {
this.pushUploadResult(String(ctx.id), { this.pushUploadResult(String(ctx.id), {
id: `seg_${String(ctx.id)}_${normalizedSegmentNo}_${Date.now()}`, id: `seg_${String(ctx.id)}_${normalizedSegmentNo}_${Date.now()}`,
@@ -1035,10 +1035,88 @@ export default {
} }
return headers; return headers;
}, },
/** 上传音频文件名租户id_手机号_年月日时分秒租户id、手机号后各有一个下划线多段录音段号>1 时末尾再追加 _段号 */
getAudioUploadFileName(options = {}) {
let tenantId = '';
let phone = '';
try {
tenantId = String(uni.getStorageSync('backend-tenant-id') || '').trim();
} catch (e) {}
try {
const raw = this.currentUserPhone || '';
const login = uni.getStorageSync('backend-login-response') || {};
const fallback = login.phone || login.userName || '';
phone = String(raw || fallback || '').replace(/\D/g, '');
} catch (e) {}
const d = new Date();
const pad = (n) => String(n).padStart(2, '0');
const ts = `${d.getFullYear()}${pad(d.getMonth() + 1)}${pad(d.getDate())}${pad(d.getHours())}${pad(d.getMinutes())}${pad(d.getSeconds())}`;
const seg = Number(options.segmentNo);
const segSuffix = Number.isFinite(seg) && seg > 1 ? `_${seg}` : '';
const ext = typeof options.ext === 'string' && options.ext ? options.ext : '.mp3';
const dotExt = ext.startsWith('.') ? ext : `.${ext}`;
const tenantPrefix = tenantId ? `${tenantId}_` : '';
const phonePrefix = phone ? `${phone}_` : '';
const base = `${tenantPrefix}${phonePrefix}${ts}${segSuffix}`.replace(/[/\\:*?"<>|]/g, '_') || `upload_${ts}${segSuffix}`;
return `${base}${dotExt}`;
},
/**
* 微信小程序等环境下 multipart 的原始文件名来自本地路径最后一段;临时路径常为随机串甚至带异常后缀。
* 复制到 USER_DATA_PATH 并使用规范文件名再上传,后端 getOriginalFilename / 落盘名才能与 fileName 参数一致。
*/
prepareAudioFileForUpload(tempPath, displayFileName) {
return new Promise((resolve) => {
if (!tempPath || !displayFileName) {
resolve({ uploadPath: tempPath, tempCopyPath: null });
return;
}
const baseName = (() => {
const seg = String(tempPath).split(/[/\\]/).pop() || '';
return seg.split('?')[0] || '';
})();
const needsRename =
baseName !== displayFileName ||
baseName.includes('=') ||
/\.durationTime=/i.test(baseName);
let userDataPath = '';
try {
userDataPath = (uni.env && uni.env.USER_DATA_PATH) || '';
} catch (e) {}
if (!userDataPath && typeof wx !== 'undefined' && wx.env) {
userDataPath = wx.env.USER_DATA_PATH || '';
}
if (!needsRename || !userDataPath || typeof uni.getFileSystemManager !== 'function') {
resolve({ uploadPath: tempPath, tempCopyPath: null });
return;
}
const destPath = `${String(userDataPath).replace(/\/+$/, '')}/${displayFileName}`;
uni.getFileSystemManager().copyFile({
srcPath: tempPath,
destPath,
success: () => resolve({ uploadPath: destPath, tempCopyPath: destPath }),
fail: (err) => {
console.warn('prepareAudioFileForUpload copyFile failed:', err);
resolve({ uploadPath: tempPath, tempCopyPath: null });
},
});
});
},
safeUnlinkAudioCopy(filePath) {
if (!filePath || typeof uni.getFileSystemManager !== 'function') {
return;
}
try {
uni.getFileSystemManager().unlink({ filePath, fail: () => {} });
} catch (e) {}
},
async uploadFileForRecord(item, selectedFile, options = {}) { async uploadFileForRecord(item, selectedFile, options = {}) {
const recordId = String(item.id); const recordId = String(item.id);
const segmentNo = Number(options.segmentNo) || 1; const segmentNo = Number(options.segmentNo) || 1;
const durationSeconds = Math.max(0, Number(options.durationSeconds) || 0); const durationSeconds = Math.max(0, Number(options.durationSeconds) || 0);
const audioDurationMinutesStr = (() => {
const m = durationSeconds / 60;
return Number.isFinite(m) ? String(Math.round(m * 1e6) / 1e6) : '0';
})();
const fileSize = Math.max(0, Number(selectedFile?.size) || 0); const fileSize = Math.max(0, Number(selectedFile?.size) || 0);
const resultId = `seg_${recordId}_${segmentNo}_${Date.now()}`; const resultId = `seg_${recordId}_${segmentNo}_${Date.now()}`;
this.pushUploadResult(recordId, { this.pushUploadResult(recordId, {
@@ -1051,20 +1129,26 @@ export default {
message: '', message: '',
}); });
this.increaseUploadingCount(recordId); this.increaseUploadingCount(recordId);
let tempCopyPath = null;
try { try {
const targetFileName = this.getAudioUploadFileName({ segmentNo });
const prep = await this.prepareAudioFileForUpload(selectedFile.path, targetFileName);
const uploadPath = prep.uploadPath;
tempCopyPath = prep.tempCopyPath;
const maxAttempt = options.retryOnceOnFail ? 2 : 1; const maxAttempt = options.retryOnceOnFail ? 2 : 1;
let lastErrorMessage = ''; let lastErrorMessage = '';
for (let attempt = 1; attempt <= maxAttempt; attempt += 1) { for (let attempt = 1; attempt <= maxAttempt; attempt += 1) {
const uploadRes = await uni.uploadFile({ const uploadRes = await uni.uploadFile({
url: getApiUrl('/api/audio/upload'), url: getApiUrl('/api/audio/upload'),
filePath: selectedFile.path, filePath: uploadPath,
name: 'file', name: 'file',
formData: { formData: {
id: item.id, id: item.id,
audioId: item.id, audioId: item.id,
audioDuration: audioDurationMinutesStr,
customerId: item.customerId || '', customerId: item.customerId || '',
customerName: item.customerName || '', customerName: item.customerName || '',
fileName: selectedFile.name || `service_file_${Date.now()}`, fileName: targetFileName,
compress: true compress: true
}, },
header: this.getAuthHeaders(), header: this.getAuthHeaders(),
@@ -1110,6 +1194,7 @@ export default {
}); });
return false; return false;
} finally { } finally {
this.safeUnlinkAudioCopy(tempCopyPath);
this.decreaseUploadingCount(recordId); this.decreaseUploadingCount(recordId);
} }
}, },

View File

@@ -1 +1 @@
"use strict";exports.envConfig={apiEnv:"prod"}; "use strict";exports.envConfig={apiEnv:"local"};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long