小程序语音上传到 dify 415 的解决办法

71 天前
 lyxxxh2

问题

用 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
        })
    }
})()

698 次点击
所在节点    微信
0 条回复

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1142732

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX