用 curl 正常
curl -X POST 'https://xxx/audio-to-text' --header 'Authorization: xxx' --form 'file=@xxx/1.mp3;type=audio/mp3'
小程序: 一直 415
对了半天: mine-type
不一样。
wx.uploadFile
不支持 mine-type
,让 ai 重新写了,终于解决了。
cv 给 ai,让 ai 参考就行
// 修复的方案 2:正确处理二进制文件数据 (async function testAudioAPIFixed() { console.log('=== 修复的手动构造 multipart 测试 ===') const audioUrl = 'xxx/1.mp3' const apiCOnfig= { baseUrl: 'https://xxx/v1', apiKey: 'xxxx' } try { // 下载文件 const downloadResult = await new Promise((resolve, reject) => { wx.downloadFile({ url: audioUrl, success: resolve, fail: reject }) }) // 读取文件数据为 ArrayBuffer const fileData = await new Promise((resolve, reject) => { wx.getFileSystemManager().readFile({ filePath: downloadResult.tempFilePath, success: resolve, fail: reject }) }) console.log('文件读取成功,大小:', fileData.data.byteLength) // 手动构造 multipart/form-data - 正确处理二进制数据 const boundary = '----formdata-' + Date.now() const encoder = new TextEncoder() // 构造表单头部(文本部分) let formHeader = '' formHeader += `--${boundary}\r\n` formHeader += `Content-Disposition: form-data; name="file"; filename="1.mp3"\r\n` formHeader += `Content-Type: audio/mp3\r\n\r\n` // 关键:设置正确的 MIME 类型 // 构造表单尾部(文本部分) const formFooter = `\r\n--${boundary}--\r\n` // 转换文本部分为 ArrayBuffer const headerBuffer = encoder.encode(formHeader) const footerBuffer = encoder.encode(formFooter) // 组合所有数据:头部 + 文件数据 + 尾部 const totalLength = headerBuffer.byteLength + fileData.data.byteLength + footerBuffer.byteLength const finalBuffer = new ArrayBuffer(totalLength) const finalView = new Uint8Array(finalBuffer) let offset = 0 // 复制头部 finalView.set(new Uint8Array(headerBuffer), offset) offset += headerBuffer.byteLength // 复制文件数据(保持原始二进制格式) finalView.set(new Uint8Array(fileData.data), offset) offset += fileData.data.byteLength // 复制尾部 finalView.set(new Uint8Array(footerBuffer), offset) console.log('multipart 数据组装完成,总大小:', finalBuffer.byteLength) // 发送请求 const result = await new Promise((resolve, reject) => { wx.request({ url: `${apiConfig.baseUrl}/audio-to-text`, method: 'POST', header: { 'Authorization': `Bearer ${apiConfig.apiKey}`, 'Content-Type': `multipart/form-data; boundary=${boundary}` }, data: finalBuffer, // 发送完整的 ArrayBuffer success: resolve, fail: reject }) }) console.log('修复版 multipart 结果:', result) if (result.statusCode === 200) { const respOnseData= typeof result.data === 'string' ? JSON.parse(result.data) : result.data console.log(' 成功!', responseData) wx.showModal({ title: '修复版 multipart 成功', content: `识别结果: ${responseData.text}`, showCancel: false }) } else { console.error(' 失败:', result.statusCode, result.data) wx.showModal({ title: '修复版 multipart 失败', content: `状态码: ${result.statusCode}\n 错误: ${result.data}`, showCancel: false }) } } catch (error) { console.error(' 修复版 multipart 错误:', error) wx.showModal({ title: '修复版 multipart 异常', content: error.message, showCancel: false }) } })()