微信小程序上传图片后立即展示该图片的最佳实践

业务场景及实践遇到的问题

  1. 业务场景
  • 微信小程序内,需要实现一个类似微博的图文列表,支持顶部新增图文,新增成功之后,列表立即加载新增的图文记录。
  1. 遇到的问题
  • 微信小程序对应的服务端使用了微信云托管,所以选择使用云托管中的对象存储服务来保存图片。
  • 使用wx.cloud.uploadFile上传图片,图片上传成功后,image标签对应的src使用官方推荐的loadcos转换方法来转换fileId得到用于公开访问的url,但是图片都不能正常展示出来。
javascript 复制代码
function loadcos(url){
  var res = url
  if (url.indexOf('cloud://') === 0) {
    var first = url.indexOf('.')
    var end = url.indexOf('/', first)
    res = 'https://' + url.slice(first + 1, end) + '.tcb.qcloud.la/' + url.slice(end + 1, url.length)
  }
  return res
}

module.exports={
  loadcos:loadcos
}

在微信开发者工具中会看到有两次对应的图片网络请求:

  • 第一个请求的域名是 tcb.qcloud.la,而第二个请求的域名是 cos.ap-shanghai.myqcloud.com

  • 这表明可能存在两种不同的访问路径:

    • tcb.qcloud.la 是微信云存储的默认域名。
    • cos.ap-shanghai.myqcloud.com 是腾讯云 COS 的 CDN 域名。
  • 第一个请求返回404,第二个请求返回No content

分析可能的原因:tcb.qcloud.la域名的url是loadcos方法转换得到的,返回404,大概率是因为云存储有做读写分离,图片上传到写服务,但是还没同步到读服务;cos.ap-shanghai.myqcloud.com域名的url请求应该是微信小程序内部实现的机制,在不能正确从云存储加载到图片时,再请求一遍存储对应区域的CDN,多做一次尝试,但是读取的还是云存储的读服务,所以还是不能正确获取图片文件。

解决方案

在图片上传到云端后需要立即展示的情况下。通过直接使用本地临时文件路径(tmpFilePath)作为 <image>src 属性值,可以绕过网络延迟和云存储同步的问题,从而实现图片的即时加载。

以下是详细分析:


为什么使用 tmpFilePath 能立即加载图片?

  1. 本地文件路径

    • tmpFilePath 是用户选择图片时生成的本地临时文件路径(例如:wx.chooseImage 返回的 tempFilePaths)。
    • 这个路径指向的是设备本地的文件,因此可以直接读取,无需等待网络传输或云存储同步。
  2. 避免网络延迟

    • 上传图片到云端后,文件可能需要时间写入存储系统,并同步到 CDN。如果直接使用云端路径(如 fileIDCDN URL),可能会因为同步延迟导致图片无法立即加载。
    • 使用 tmpFilePath 可以完全避免这些网络问题。
  3. 用户体验提升

    • 用户在选择图片后,可以立即看到图片预览,而无需等待上传完成。这种即时反馈显著提升了用户体验。

代码示例

以下是一个完整的代码示例,展示如何在微信小程序中实现这一方案:

javascript 复制代码
Page({
  data: {
    tempFilePath: '', // 用于存储本地临时文件路径
    cloudFileURL: '', // 用于存储云端文件 URL
  },

  // 选择图片并显示临时文件
  chooseImage() {
    wx.chooseImage({
      count: 1, // 允许选择一张图片
      success: (res) => {
        const tempFilePath = res.tempFilePaths[0]; // 获取临时文件路径
        this.setData({
          tempFilePath: tempFilePath, // 设置临时文件路径为图片 src
        });

        // 上传图片到云端
        this.uploadImage(tempFilePath);
      },
      fail: (err) => {
        console.error('选择图片失败:', err);
      },
    });
  },

  // 上传图片到云端
  uploadImage(tempFilePath) {
    wx.cloud.uploadFile({
      cloudPath: `images/${Date.now()}.jpg`, // 云端存储路径
      filePath: tempFilePath, // 本地临时文件路径
      success: (uploadRes) => {
        console.log('图片上传成功:', uploadRes.fileID);

        // 获取云端文件的临时访问链接
        wx.cloud.getTempFileURL({
          fileList: [uploadRes.fileID],
          success: (urlRes) => {
            const cloudFileURL = urlRes.fileList[0].tempFileURL;
            this.setData({
              cloudFileURL: cloudFileURL, // 更新云端文件 URL
            });
            console.log('获取云端文件 URL 成功:', cloudFileURL);
          },
          fail: (err) => {
            console.error('获取云端文件 URL 失败:', err);
          },
        });
      },
      fail: (err) => {
        console.error('图片上传失败:', err);
      },
    });
  },
});

WXML 示例

html 复制代码
<view>
  <!-- 显示图片 -->
  <image 
    :src="cloudFileURL || tempFilePath" 
    mode="aspectFit" 
    style="width: 100%; height: 300px;">
  </image>

  <!-- 选择图片按钮 -->
  <button bindtap="chooseImage">选择图片</button>
</view>

逻辑解释

  1. 选择图片

    • 用户点击按钮触发 chooseImage 方法。
    • 使用 wx.chooseImage 选择图片,获取临时文件路径 tempFilePath
    • tempFilePath 设置为 <image>src,立即显示图片。
  2. 上传图片

    • 同时调用 uploadImage 方法将图片上传到云端。
    • 上传完成后,通过 wx.cloud.getTempFileURL 获取云端文件的临时访问链接。
  3. 更新云端 URL

    • 当云端文件 URL 可用时,更新 cloudFileURL
    • <image>src 会自动切换为云端 URL,确保图片持久化。

优点

  • 即时显示:用户选择图片后,图片立即显示,无需等待上传完成。
  • 无缝切换:当云端 URL 可用时,图片源会自动切换为云端地址,保证后续访问的稳定性。
  • 减少延迟:避免了因网络延迟或云存储同步导致的图片加载失败。

注意事项

  1. 临时文件的有效期

    • tmpFilePath 是一个临时文件路径,通常只在当前页面或会话中有效。如果需要长期保存图片,必须上传到云端并使用云端 URL。
  2. 错误处理

    • 如果上传失败,确保有相应的错误提示机制,并允许用户重新上传。
  3. 性能优化

    • 如果图片较大,可以在上传前进行压缩(如使用 wx.compressImage),以减少上传时间和流量消耗。

总结

通过使用 tmpFilePath 作为图片的初始 src,可以实现图片的即时加载,显著提升用户体验。同时,结合云端 URL 的动态切换,可以确保图片的持久化和长期可用性。这种方案适用于大多数需要快速预览图片的场景,是微信小程序开发中常用的最佳实践之一。

相关推荐
天天扭码39 分钟前
零基础 | 入门前端必备技巧——使用 DOM 操作插入 HTML 元素
前端·javascript·dom
咖啡虫1 小时前
css中的3d使用:深入理解 CSS Perspective 与 Transform-Style
前端·css·3d
拉不动的猪1 小时前
设计模式之------策略模式
前端·javascript·面试
旭久1 小时前
react+Tesseract.js实现前端拍照获取/选择文件等文字识别OCR
前端·javascript·react.js
独行soc2 小时前
2025年常见渗透测试面试题-红队面试宝典下(题目+回答)
linux·运维·服务器·前端·面试·职场和发展·csrf
uhakadotcom2 小时前
Google Earth Engine 机器学习入门:基础知识与实用示例详解
前端·javascript·面试
麓殇⊙2 小时前
Vue--组件练习案例
前端·javascript·vue.js
outstanding木槿2 小时前
React中 点击事件写法 的注意(this、箭头函数)
前端·javascript·react.js
会点php的前端小渣渣2 小时前
vue的计算属性computed的原理和监听属性watch的原理(新)
前端·javascript·vue.js
_一条咸鱼_3 小时前
深入解析 Vue API 模块原理:从基础到源码的全方位探究(八)
前端·javascript·面试