uniapp app分享到微信,图片太大,导致报错:share:fail [Share微信分享:-3]Unable to send, https://ask.dcloud.net.cn/article
·
项目场景:
本博在做一款安卓+IOS+小程序的项目的时候。产品有一个业务是app、小程序需要分享小程序链接到微信中。但是分享的时候有些时候能分享出去,但是有时候又分享不出去,经过对所有参数的排查定位到imageUrl参数。
问题描述
官方文档上描述type=图文的时候,推荐使用20kb以下的图片(实测可以分享100KB以下的图片)

解决方案:
Tips: 这里面在图片上传的时候有个陷阱,应为图片虽然经过压缩,但是图片的名称不会因为压缩图片而改变。如果直接传入oss之后可能会导致图片覆盖问题(或者传不上去),在这个问题上可以分为前端和后端两种解决方法,前端的话可以通过uni.savefile去进行保存后再上传,后台的话更简单一些,生成一个唯一的图片名称就可以了!
以下是封装的一个可以同时适配小程序和app的函数,只调用主函数compressImg2Share传入图片的Url。原理就是递归的压缩图片,这样可以达到的效果是将图片压缩到100KB以下,但是无法准确的压缩到100KB,实现原理是通过压缩图片的宽高以达到压缩图片大小的目的,因为图片大小是像素点的色彩复杂程度决定的,所以无法通过宽高去线性的压缩到目标大小。
如果想要精确的压缩到100KB,可以通过增大compressRate参数改变压缩的细腻度(但是这样会增加应用的负载)。
// compress.js 压缩文件
/**
* 获取文件基本信息
* @param {String} url 文件地址
*/
export function getFileInfoo(url) {
return new Promise((resolve, reject) => {
if (!url) {
return reject('url is empty')
}
uni.downloadFile({
url: url,
success: (dRes) => {
if (dRes.statusCode !== 200) {
reject('downloadFile Error: 下载失败')
return
}
const tempPath = dRes.tempFilePath
// 获取源文件名称和后缀
const fileName = url.substring(url.lastIndexOf('/') + 1)
const file = {
width: 0,
height: 0,
size: 0,
temp: tempPath,
name: fileName
}
const checkReturn = () => {
if (!file.width || !file.height || !file.size) return;
resolve(file)
}
uni.getFileInfo({
filePath: tempPath,
success: (res) => {
if (!res.size) reject('getFileInfo Error: 文件大小错误')
file.size = res.size / 1024;
checkReturn()
}
})
uni.getImageInfo({
src: tempPath,
success: (res) => {
if (!res.width || !res.height) reject('getImageInfo Error: 文件宽高获取失败')
file.width = res.width;
file.height = res.height;
checkReturn()
}
})
},
fail: (err) => {
console.log("下载文件失败:", err)
}
})
})
}
/**
* 递归压缩图片到指定大小 - 可省略
* @param {string} url - 图片 URL
* @param {number} targetSize - 目标文件大小 (KB),默认 20KB
* @returns {Promise<string>} - 压缩后的图片 URL
*/
export function compressImageRecursive(url, targetSize = 20) {
return new Promise((resolve, reject) => {
if (!url) {
return reject('url is empty')
}
getFileInfoo(url).then(res => {
console.log(`原始图片信息:`, {
width: res.width,
height: res.height,
size: res.size.toFixed(2) + 'KB'
});
if (res.size <= targetSize) {
resolve(url)
return
}
compressLoop(res.temp, res.width, res.height, res.size, targetSize, url, 1)
.then(resolve)
.catch(reject)
}).catch(reject)
})
}
/** 循环压缩图片
* @param {String} tempPath Uniapp临时地址
* @param {Number} width 当前宽度
* @param {Number} height 当前高度
* @param {Number} size 当前大小 - KB
* @param {Number} targetSize 目标大小
* @param {Number} count 压缩次数
*/
function compressLoop(tempPath, width, height, size, targetSize, count) {
return new Promise((resolve, reject) => {
const compressRate = 0.9
const newWidth = Math.floor(width * compressRate)
const newHeight = Math.floor(height * compressRate)
console.log(`第${count}次压缩:`, {
width: newWidth,
height: newHeight,
currentSize: size.toFixed(2) + 'KB',
targetSize: targetSize + 'KB'
})
if (newWidth < 50 || newHeight < 50) {
console.warn('已达到压缩极限')
resolve(tempPath)
return
}
uni.compressImage({
src: tempPath,
compressedWidth: newWidth,
compressedHeight: newHeight,
success: async (resc) => {
const newTempPath = resc.tempFilePath
uni.getFileInfo({
filePath: newTempPath,
success: async (fileRes) => {
const newSize = fileRes.size / 1024
console.log(`压缩后:${newSize.toFixed(2)}KB`)
if (newSize > targetSize) {
try {
const result = await compressLoop(
newTempPath,
newWidth,
newHeight,
newSize,
targetSize,
count + 1
)
resolve(result)
} catch (err) {
reject(err)
}
} else {
resolve({
temp:newTempPath,
size: newSize,
width: newWidth,
height: newHeight
})
}
},
fail: (err) => {
reject('获取文件大小失败:' + JSON.stringify(err))
}
})
},
fail: (err) => {
reject('compressImage Error: ' + JSON.stringify(err))
}
})
})
}
/**
* 分享到微信,图片压缩方法 - 主方法
* @param {String} url 图片地址
*/
export function compressImg2Share(url) {
return new Promise((resolve, reject) => {
if (!url) {
return reject('url is empty')
}
getFileInfoo(url).then(res => {
// 已有缓存
const xccShareImgCache = storage.get(res.name)
if (xccShareImgCache) {
resolve(xccShareImgCache)
} else {
// 未发现缓存
const size = res.size / 20
const changeSize = {
width: Math.floor(res.width / size),
height: Math.floor(res.height / size),
size: Math.floor(size * 1024)
}
compressLoop(res.temp, res.width, res.height, res.size, 101, url, 1)
.then(async (resc) => {
const tempFile = resc.temp;
console.log("tempFile", tempFile)
// 上传到线上问题 - start 改成自己的上传逻辑
const upload = await doUploadsReady({
model: 'image',
name: res.name,
path: tempFile,
size: resc.size
})
if (upload) {
const {
data
} = upload;
uni.uploadFile({
url: data.host,
filePath: tempFile,
name: 'file',
formData: {
key: data.key,
policy: data.policy,
OSSAccessKeyId: data.ossAccessKeyId,
signature: data.signature
},
success: async (resu) => {
if (resu.statusCode === 204) {
const filePath = data.host + '/' + data.key;
console.log("filePath", filePath)
// 设置缓存
storage.set(res.name, filePath)
resolve(filePath)
}
},
fail: (err) => {}
});
}
// 上传到线上问题 - start
})
}
}).catch(res => {
console.log("Error", res)
})
})
}
更多推荐



所有评论(0)