5***@qq.com
5***@qq.com
  • 发布:2026-03-30 14:33
  • 更新:2026-03-30 14:34
  • 阅读:56

【报Bug】使用uni.chooseImage选择图片后获取的临时地址偶发性的无法上传到后端,后端获取到的图片是null

分类:uni-app

产品分类: uniapp/App

PC开发环境操作系统: Mac

PC开发环境操作系统版本号: 15.7.4

HBuilderX类型: 正式

HBuilderX版本号: 5.05

手机系统: Android

手机系统版本号: Android 15

手机厂商: OPPO

手机机型: oppo

页面类型: vue

vue版本: vue2

打包方式: 云端

项目创建方式: HBuilderX

示例代码:
chooseImage: function() {  
            let that = this;  
            var sourceTypeArr = ['camera'];  
            var imageLimit = 6;  
            if (plus.storage.getItem("zhyl_album_open") == "1" && that.imageList.length < 2) {  
                sourceTypeArr.push("album");  

            }  
            if (plus.storage.getItem("zhyl_album_open") == "1") {  
                imageLimit = 8;  
            }  

            if (that.imageList.length < imageLimit && !that.isImageUploading) {  

                var Manifest;  
                if (plus.os.name == "Android") {  
                    Manifest = plus.android.importClass("android.Manifest");  
                }  
                checkAndRequestPermission(plus.os.name == "Android" ? Manifest.permission.CAMERA : "camera",  
                    function() {  
                        that.isImageUploading = true;  

                        uni.chooseImage({  
                            count: 1,  
                            sourceType: sourceTypeArr, //从相册选择  
                            success: function(res) {  
                                //压缩图片,大于200KB进行压缩  
                                console.log("image size:" + res.tempFiles[0].size)  
                                if (res.tempFiles[0].size > 200 * 1024) {  
                                    uni.compressImage({  
                                        src: res.tempFilePaths[0],  
                                        quality: plus.os.name == "iOS" ? 60 : 70,  
                                        width: "1024px",  
                                        success: result => {  
                                            console.log("compress image:" + result  
                                                .tempFilePath)  
                                            if (result.tempFilePath) {  
                                                that.uploadFile(result.tempFilePath,  
                                                    true, 1);  

                                            } else {  
                                                uni.showToast({  
                                                    icon: "none",  
                                                    title: "压缩图片出现问题,请稍后重试"  
                                                })  
                                            }  

                                        },  
                                        fail: function(err) {  
                                            console.log("compress image fail:", JSON.stringify(err));  
                                            uni.showToast({  
                                                icon: "none",  
                                                title: "压缩图片失败,将以原图上传"  
                                            })  
                                            if (res.tempFilePaths[0]) {  
                                                that.uploadFile(res.tempFilePaths[0],  
                                                    true, 2);  
                                            } else {  
                                                uni.showToast({  
                                                    icon: "none",  
                                                    title: "压缩图片获取图片失败"  
                                                })  
                                            }  
                                        }  
                                    })  
                                } else {  
                                    console.log("image:" + res.tempFilePaths[0])  
                                    if (res.tempFilePaths[0]) {  
                                        that.uploadFile(res.tempFilePaths[0], true, 3);  
                                    } else {  
                                        uni.showToast({  
                                            icon: "none",  
                                            title: "获取图片失败"  
                                        })  
                                    }  

                                }  

                            },  
                            fail: function() {  
                                uni.showToast({  
                                    icon: "none",  
                                    title: "请重新拍摄"  
                                })  
                                that.isImageUploading = false;  
                            }  
                        });  
                    })  

            } else if (that.imageList.length >= imageLimit) {  
                uni.showModal({  
                    title: '提示',  
                    content: "最多只能上传" + imageLimit + "张图片",  
                    showCancel: false  
                });  
            }  

        },  
        //上传图片或上传录音文件  
        uploadFile: function(file, isImage, type) {  
            uni.showLoading({  
                mask: true  
            });  
            let that = this;  
            let md5Obj = this.$api.getMd5Str("zzlymobile");  
            let userToken = uni.getStorageSync('cg_user_token');  
            let signature = userToken.substring(0, 10) + md5Obj.md5.substring(0, 10) + userToken.substring(10);  
            var param = {  
                signature: signature,  
                tt: md5Obj.time,  
                api_token: Utils.getApiToken("zhyl/service/fillInfo"),  
                log_id: that.serviceDetail.log_id,  
                uid: plus.storage.getItem('cg_user_id'),  
                user_token: userToken,  
                mobile: plus.storage.getItem("cg_mobile"),  
                host: this.baseUrl  
            };  
            uni.uploadFile({  
                url: this.baseUrl + 'zhyl/service/fillInfo', //仅为示例,非真实的接口地址  
                filePath: file,  
                name: isImage ? 'img' : 'record',  
                formData: param,  
                success: function(result) {  
                    uni.hideLoading();  
                    if (result.data) {  
                        let res = JSON.parse(result.data);  
                        if (res.error_code == 0) {  
                            if (isImage) {  
                                if (res.data.new_image) {  
                                    that.imageList.push(res.data.new_image);  
                                    that.uploadPicAndPoint(1, res.data.new_image);  
                                } else {  
                                    uni.getFileInfo({  
                                        filePath: file,  
                                        success: (fileRes) => {  
                                            uni.showToast({  
                                                icon: "none",  
                                                title: fileRes.error_msg || (  
                                                    "读取文件成功,文件大小:" + fileRes  
                                                    .size + " " + file + "  " +  
                                                    type)  
                                            })  
                                        },  
                                        fail: (error) => {  
                                            uni.showToast({  
                                                icon: "none",  
                                                title: (error.errMsg || "读取文件失败") +  
                                                    file + "  " + type  
                                            })  
                                        }  
                                    })  
                                }  
                            } else {  
                                that.recordFilePath = that.audio.src;  
                                that.isRecordUploaded = true;  
                            }  
                        } else if (res.error_code == 30001 || res.error_code == 201) {  
                            plus.storage.removeItem("cg_user_token");  
                            plus.storage.removeItem("lylz_user_token");  
                            plus.storage.removeItem("lylz_user_id");  
                            let link = '/hybrid/html/pages/login/login.html';  
                            uni.navigateTo({  
                                url: '/pages/WebviewTemplateNoHeader?link=' +  
                                    encodeURIComponent(link)  
                            });  
                        } else {  
                            uni.showToast({  
                                icon: "none",  
                                title: res.error_msg || "图片或录音上传失败,请重新拍照上传"  
                            })  
                            if (!isImage) {  
                                that.deleteAudioFile(true);  
                            }  
                        }  
                    } else {  
                        uni.showToast({  
                            icon: "none",  
                            title: res.error_msg || "图片或录音上传失败,请稍后重试"  
                        })  
                        if (!isImage) {  
                            that.deleteAudioFile(true);  
                        }  
                    }  
                    that.isImageUploading = false;  
                },  
                fail: function(err) {  
                    uni.hideLoading();  
                    console.log(JSON.stringify(err));  
                    uni.showToast({  
                        icon: "none",  
                        title: "接口请求异常"  
                    })  
                    that.isImageUploading = false;  
                    if (!isImage) {  
                        that.deleteAudioFile(true);  
                    }  
                }  
            });  
        },,

操作步骤:

不是必现的

预期结果:

用户上传图片成功

实际结果:

用户上传图片失败

bug描述:

前端通过uni.chooseImage拍照获取图片请求后端上传接口,后端无法读取到图片也没法上传,这个问题是偶发性的,不是必现的,每隔几天就有用户给我们反馈这个问题,
前端拍照上传的代码如图所示,用户手机上错误提示信息如图,根据图片提示信息可以看到uni.chooseImage(获取到了图片地址,但是获取不到图片内容

2026-03-30 14:33 负责人:无 分享
已邀请:
Ask小助手

Ask小助手 - Ask社区AI助手

欢迎到专业群( uni-app 官方技术交流群 1 ) 咨询,群中有相关专业的管理员和群友。

作为DCloud官方人员,我对这个bug反馈进行如下评审:

一、反馈内容完整性评估

优点:

  • 提供了较为完整的代码示例,包含chooseImagecompressImageuploadFile的完整调用链
  • 环境信息较为齐全(HBuilderX 5.05、Android 15、Vue2、OPPO设备)
  • 问题现象描述相对清晰(偶发性、后端获取为null、有临时路径但无内容)

不足与需补充:

  1. 缺少关键错误日志:虽然提到"用户手机上错误提示信息如图",但实际未提供截图或具体的错误码/错误信息
  2. 复现细节严重不足:仅说明"不是必现",但未提供发生频率(如1/10次还是1/1000次)、特定机型限制、网络环境(WiFi/4G/5G)、图片大小特征等
  3. 后端接收细节缺失:未说明后端接收到的请求体结构、Content-Type、文件字段是否为空对象还是完全缺失
  4. 调试信息不足:代码中虽有uni.getFileInfo的调试逻辑,但未提供实际的调试输出结果

二、技术方案评审

代码层面发现的问题:

  1. 临时文件生命周期风险:根据知识库文档,"文件的临时路径,在应用本次启动期间可以正常使用",但在某些Android系统(特别是Android 15新权限体系)中,临时文件可能在压缩或上传过程中被系统清理
  2. 异步处理隐患compressImage成功后直接传递result.tempFilePath,但未验证该路径文件实际可访问性
  3. plus API混用:代码中混用plus.storage(HTML5+ API)与uni API,在Android 15新权限模型下可能存在上下文权限不一致问题

建议验证点:

  • uploadFile前增加uni.getFileInfo验证,确认文件确实存在且size > 0
  • 考虑在压缩后使用uni.saveFile将临时文件转为持久化文件后再上传,避免系统回收风险

三、平台兼容性分析

根据知识库信息,需要特别关注:

  1. Android 15权限变更:Android 15(API 35)对存储权限和临时文件访问有更严格的限制,可能影响uni.chooseImage返回的临时文件路径在后续操作中的可访问性
  2. Google Play照片权限政策:如应用需上架Google Play,受照片和视频权限政策影响,可能需要使用uni-chooseSystemMedia插件替代原生API

四、排查建议(基于知识库)

立即排查项:

  1. uploadFile方法开头增加文件存在性验证:

    uni.getFileInfo({  
    filePath: file,  
    success: (info) => {  
        if(info.size === 0) {  
            console.error('文件大小为0,可能已被清理');  
        }  
    }  
    })

    本助手使用国产模型,生成代码可能不准确。专业的代码生成需要全球顶尖的AI Coding模型。推荐使用uni-agent

  2. 替代方案:如问题持续,建议使用插件市场更稳定的方案:

需要用户提供的信息:

  1. 具体的错误提示截图或日志(包括console.log输出)
  2. 发生问题时的具体场景(如:是否切换过应用、是否长时间停留在选择页面、图片大小范围)
  3. 后端接收到的HTTP请求体原始内容(确认文件字段是null还是空对象)

结论: 该反馈基本成立,但属于偶发性系统权限或资源回收问题,非必现bug。建议优先验证文件生命周期管理,并考虑使用持久化存储或成熟的上传插件替代当前实现。

内容为 AI 生成,仅供参考

要回复问题请先登录注册