修复微信小程序获取头像的bug,微信小程序新版头像API使用

接着我之前发布的一篇文章:微信小程序上传头像的临时路径,持久化保存到服务器与数据库(nodejs后台开发)_盒子猫君的博客-CSDN博客

今天我就来解决掉之前的问题吧!

从之前的后台报错来看,获取到的tempFilePath值和avatarUrl的值相同,都是http://tmp,不过头像都已经上传成功了并存到了数据库。而在真机调试时,用户选择头像后,是无法保存到数据库和对应的文件夹中的。

经过分析后,原因是在微信小程序中,选择头像后会返回一个临时文件路径(tempFilePath)供开发者进行上传和保存操作。真机调试时,是无法直接访问和保存这个临时文件的,所以在该代码中直接读取tempFilePath可能会出现问题。

解决方案下面就有了:

使用wx.saveFile保存临时文件,并将保存的文件路径作为参数传递给wx.uploadFile进行上传操作:

onChooseAvatar(e) {
    const { avatarUrl } = e.detail

    wx.saveFile({
        tempFilePath: avatarUrl,
        success(res) {
            const savedFilePath = res.savedFilePath
            console.log("保存的头像文件路径:" + savedFilePath)

            // 上传保存的图片
            wx.uploadFile({
                url: config.apiUrl + '/api/avatarUrl',
                filePath: savedFilePath,
                name: 'file',
                formData: {
                    'openid': wx.getStorageSync('openid')
                },
                success(res) {
                    console.log('uploadFile响应数据:', res.data);
                    try {
                        const data = JSON.parse(res.data)
                        console.log('upload success');
                        console.log("成功获取到用户头像存入数据库:", data.path);
                        wx.showToast({
                            title: '头像上传成功',
                            icon: 'success',
                        });
                    } catch(e) {
                        console.log('返回数据不是json格式,无法解析');
                        wx.showToast({
                            title: '头像上传失败',
                            icon: 'error'
                        });
                    }
                },
                fail(res) {
                    console.log('upload fail');
                }
            })
        },
        fail(res) {
            console.log('saveFile fail');
        }
    })
},

在后台路由代码中,利用Node.js的文件流将临时文件保存到指定目录,然后使用保存后的文件路径进行数据库操作:

const express = require('express');
const router = express.Router();
const sql = require('../sql');
const multer = require('multer');
const fs = require('fs');

// 设置文件上传的目录
const storage = multer.diskStorage({
    destination: function(req, file, cb) {
        cb(null, './public/upload')
    },
    filename: function(req, file, cb) {
        cb(null, Date.now() + '-' + file.originalname)
    }
})

const upload = multer({ storage: storage })

router.post('/avatarUrl', upload.single('file'), (req, res) => {
    console.log('Received file:', req.file);
    console.log('Received body:', req.body);

    const openid = req.body.openid;
    const tempFilePath = req.file.path;
    const avatarUrl = 'https://like.likehistory.top/upload/' + req.file.filename;

    // 将临时文件保存到指定目录
    const savedFilePath = './public/saved/' + req.file.filename;
    const readStream = fs.createReadStream(tempFilePath);
    const writeStream = fs.createWriteStream(savedFilePath);
    readStream.pipe(writeStream);

    // 创建MySQL查询
    const sqlStr = 'SELECT * FROM wxusers WHERE openid = ?';

    // 查询数据库
    sql.query(sqlStr, [openid], function(err, result) {
        if (err) {
            console.error(err);
            res.status(500).send('Database error');
        } else {
            // 检查是否有匹配的openId
            if (result.length > 0) {
                const sqlStr = `UPDATE wxusers SET avatarUrl = '${avatarUrl}' WHERE openid = '${openid}'`;
                sql.query(sqlStr, (err, result) => {
                    if (err) throw err;
                    res.json({ path: avatarUrl });
                });
                console.log("更新新路径", avatarUrl);
            } else {
                const sqlStr = `INSERT INTO wxusers (openid, avatarUrl) VALUES ('${openid}','${avatarUrl}')`;
                sql.query(sqlStr, [openid, avatarUrl], (err, result) => {
                    if (err) throw err;
                    res.json({ path: avatarUrl });
                });
                console.log("插入新路径", avatarUrl);
            }
        }
    });
});

module.exports = router;

这下终于调式成功了,不过后台告诉我:wx.saveFile 即将废弃,请使用 wx.getFileSystemManager().saveFile。所以下面再修改一下微信小程序的代码:

onChooseAvatar(e) {
    const { avatarUrl } = e.detail

    wx.getFileSystemManager().saveFile({
        tempFilePath: avatarUrl,
        success(res) {
            const savedFilePath = res.savedFilePath
            console.log("保存的头像文件路径:" + savedFilePath)

            // 上传保存的图片
            wx.uploadFile({
                url: config.apiUrl + '/api/avatarUrl',
                filePath: savedFilePath,
                name: 'file',
                formData: {
                    'openid': wx.getStorageSync('openid')
                },
                success(res) {
                    console.log('uploadFile响应数据:', res.data);
                    try {
                        const data = JSON.parse(res.data)
                        console.log('upload success');
                        console.log("成功获取到用户头像存入数据库:", data.path);
                        wx.showToast({
                            title: '头像上传成功',
                            icon: 'success',
                        });
                    } catch(e) {
                        console.log('返回数据不是json格式,无法解析');
                        wx.showToast({
                            title: '头像上传失败',
                            icon: 'error'
                        });
                    }
                },
                fail(res) {
                    console.log('upload fail');
                }
            })
        },
        fail(res) {
            console.log('saveFile fail');
        }
    })
},

最后还要在小程序的`app.json`文件中的`permission`字段中添加相关的权限配置:

"permission": {
    "scope.writePhotosAlbum": {
      "desc": "保存图片到相册"
    },
    "scope.camera": {
      "desc": "拍照功能"
    },
    "scope.userLocation": {
      "desc": "获取用户地理位置"
    }
    // 添加其他需要的权限配置
  },

当然了,我在运行上面的代码后,还是发现了另一个问题。在用户选择相册中的图片作为头像时,由于图片是异步加载的,可能会导致上传成功后头像没有立即刷新显示。为了解决这个问题,可以在上传成功后,手动更新头像的URL,至于强制刷新页面,可有可无。

onChooseAvatar(e) {
    const { avatarUrl } = e.detail;

    wx.getFileSystemManager().saveFile({
        tempFilePath: avatarUrl,
        success(res) {
            const savedFilePath = res.savedFilePath;
            console.log("保存的头像文件路径:" + savedFilePath);

            // 上传保存的图片
            wx.uploadFile({
                url: config.apiUrl + '/api/avatarUrl',
                filePath: savedFilePath,
                name: 'file',
                formData: {
                    'openid': wx.getStorageSync('openid')
                },
                success(res) {
                    console.log('uploadFile响应数据:', res.data);
                    try {
                        const data = JSON.parse(res.data);
                        console.log('upload success');
                        console.log("成功获取到用户头像存入数据库:", data.path);
                        
                        // 更新头像URL
                        this.setData({
                            avatarUrl: data.path
                        });

                        // 强制刷新页面
                        wx.reLaunch({
                            url: '/pages/index/index' // 替换成你的页面路径
                        });

                        wx.showToast({
                            title: '头像上传成功',
                            icon: 'success',
                        });
                    } catch(e) {
                        console.log('返回数据不是json格式,无法解析');
                        wx.showToast({
                            title: '头像上传失败',
                            icon: 'error'
                        });
                    }
                },
                fail(res) {
                    console.log('upload fail');
                }
            });
        },
        fail(res) {
            console.log('saveFile fail');
        }
    });
},

这篇文章就完美解决了用户上传头像的问题。大家可以参考!

猜你喜欢

转载自blog.csdn.net/qq_25501981/article/details/131521753