В последнее время работаю над сложной кросс-пятитерминальной (ПК, Н5, апплет, iOS, андроид) заявкой, которая длилась более двух месяцев. недавно вспоминая весь процесс разработки,глубоко много подводных камней,и многое приобрел.Сегодня поделюсь функцией выбора фото в веб-просмотре апплета WeChat.В данной статье полностью зафиксирован весь процесс разработки и полностью решает различные трудноизлечимые заболевания.
Углубленное исследование
Поскольку это кросс-энд, я сначала использовал его<input type="file" accept="image/*" capture="camera">
Метод простой и грубый и может быть использован, и пять терминалов едва могут получить проходной балл.Когда тест PM заканчивается после совместной отладки, опыт очень плохой.Просьба начать планирование вызова родного, так как клиент ранее предоставлял такиеbridge, так что отладку с аватаром клиента легко завершить, а остальная часть апплета прошла через бесчисленные трудности и, наконец, пришла к идеальному занавесу.
Во-первых, у меня нет опыта в этой области, да и глаза замазаны, потому что страница H5 вложена в апплетweb-view, так что ознакомьтесь с официальной документацией напрямую, апплет предоставляет более 30 API для веб-просмотра.Подробная документация. В этот момент я подумал, что это можно сделать легко, поэтому я начал продолжать. . .
развитие шаг за шагом
Просто начал использовать его непосредственно в H5wx.chooseImage
, обнаружил постоянные отчеты об ошибках в инструментах разработчикаthe permission value is offline verifying
, потихоньку начал искать и обнаружил, что его надо использовать и в веб-виде апплетаjweixinна самом деле является страницей публичной учетной записи, затем начать нажатьЭтот процессидти:
- Импорт JS-файлов
// 推荐使用1.3.2以上的版本,之前的版本很多坑😭
https://res.wx.qq.com/open/js/jweixin-1.3.2.js
// 我是直接用的npm包,目前基于1.4.0-test的版本
npm install weixin-js-sdk
- Внедрить конфигурацию проверки разрешений через интерфейс конфигурации
wx.config({
debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: '', // 必填,微信公众号的唯一标识,此处填写公众号的appId
timestamp: , // 必填,生成签名的时间戳
nonceStr: '', // 必填,生成签名的随机串
signature: '',// 必填,签名
jsApiList: [] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
});
- Обрабатывайте успешную проверку через готовый интерфейс
wx.ready(function(){
// config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
});
- Обработка неудачной проверки через интерфейс ошибок
wx.error(function(res){
// config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
});
- Определить, поддерживает ли текущая версия клиента указанный интерфейс JS.
wx.checkJsApi({
jsApiList: ['chooseImage'] // 需要检测的JS接口列表
success: function(res) {
// 以键值对的形式返回,可用的api值true,不可用为false
// 如:{"checkResult":{"chooseImage":true},"errMsg":"checkJsApi:ok"}
},
fail: function(err) {
// checkJsApi接口调用失败
}
});
- вызов интерфейса
wx.chooseImage({
count: 1, // 默认9
sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
success: function (res) {
var localIds = res.localIds; // 返回选定照片的本地ID列表,localId可以作为img标签的src属性显示图片
}
});
В этом разделе особое внимание следует уделить следующим моментам:
- неверный URL-адрес: доменное имя и использование текущей страницыappidБез привязки (доменное имя текущей H5-страницы можно настроить в доверенном доменном имени приложения в фоновом режиме официального аккаунта);
- неверная подписьОшибка подписи: рекомендуется нажатьПроверка в следующем порядке, которые могут быть параметрами, обычно переносимыми доменным именем, поэтому доменное имя каждый раз отличается, и подпись должна быть получена через доменное имя перед вызовом;
- После запуска сервиса jsapi_ticket не может быть получен, как правило, количество вызовов access_token ограничено из-за слишком большого количества вызовов, и его необходимо кэшировать на стороне сервера;
- разрешение отклонено: у официальной учетной записи нет разрешения на использование этого JSAPI (некоторые интерфейсы должны быть аутентифицированы, прежде чем их можно будет использовать);
Обрабатывать данные изображения как base64
wx.chooseImage
Полученное изображение является временным путем, и WeChat также предоставляетwx.getLocalImgData
Метод может преобразовать полученный путь в данные в формате base64, что может быть намного проще на данном этапе, но преобразованный base64 немного отличается в Android и iOS, и на это нужно обратить особое внимание:
wx.getLocalImgData({
localId: req.localIds[0].toString(),
success: function (res) {
const localData = res.localData;
let imageBase64 = '';
if (localData.indexOf('data:image') == 0) {
//苹果的直接赋值,默认生成'data:image/jpeg;base64,'的头部拼接
imageBase64 = localData;
} else {
//此处是安卓中的唯一得坑!在拼接前需要对localData进行换行符的全局替换
//此时一个正常的base64图片路径就完美生成赋值到img的src中了
imageBase64 = 'data:image/jpeg;base64,' + localData.replace(/\n/g, '');
}
}
});
загрузить изображение
Получив данные изображения в формате base64, мы можем делать все, что захотим, без использования
wx.uploadImage
а такжеwx.downloadImage
Мало того, что его нужно загружать на сервер WeChat, но и трехдневный срок увеличивает стоимость, Лучший способ — загрузить его прямо на наш собственный сервер.
Этот тип файла, который обычно взаимодействует с сервером, обычно используетсяотправить форму --multipart/form-dataспособом, который требует от нас знакомства с передачейform-dataСледовательно, необходимо преобразовать только что полученный base64 в пригодные для публикации двоичные данные.atob/btoa
Используется для кодирования и декодирования base64;
base64ToBlob(dataurl) {
let arr = dataurl.split(',');
let mime = arr[0].match(/:(.*?);/)[1];
let bstr = atob(arr[1]);
let n = bstr.length;
let u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], { type: mime });
}
хорошо, после обработки интерактивных данных вы можете загрузить их на свой сервер, после чего это эквивалентно взаимодействию изображений обычных страниц H5, которые можно загружать и скачивать😄
let param = new FormData();
param.append('headPic', imageData);
this.$http.post('/upload.json', {
headers: {
'Content-Type': 'multipart/form-data',
},
params: param,
}).then(res => {
console.log('上传成功', res);
});
окончательный эффект
wx.chooseImage
После успешного звонка iOS и Android соответственно вызывают родную фотографию и фотоальбом системы, как показано на следующем рисунке:
полный код
наконец. . . Это может подойти к концу, пока небольшая программаweb-view
успешно используетсяwx.chooseImage
, Полный код размещен ниже, пожалуйста, обратитесь к 😄
<template>
<div class="card-avatar">
<img
:src="avatarUrl"
>
<div
class="choose-image"
@click="chooseImage"
/>
</div>
</template>
<script>
import wx from 'weixin-js-sdk';
const imgUrl = require('../../common/assets/images/default-avatar.png');
export default {
name: 'Card',
components: {
},
props: {
},
data() {
return {
avatarUrl: imgUrl,
};
},
computed: {
},
watch: {
},
mounted() {
this.getWxConfigDatas();
},
methods: {
getWxConfigDatas() {
const params = {
checkCode: getUrlParams().checkCode, // 从地址栏获取checkCode用于校验signature
};
this.$http.get('/signature.json', { params }).then(res => {
if (res.content.data && res.content.data.signature) {
this.registereWxApi(res.content.data.signature);
}
});
},
registereWxApi(data) {
wx.config({
// debug: true,
jsApiList: ['chooseImage', 'getLocalImgData'],
appId: data.appId,
timestamp: data.timestamp,
nonceStr: data.nonceStr,
signature: data.signature,
});
},
chooseImage() {
let that = this;
if (window.__wxjs_environment === 'miniprogram') {
wx.miniProgram.getEnv(function(res) {
if (res.miniprogram) {
wx.checkJsApi({
jsApiList: ['chooseImage', 'getLocalImgData'],
success: function(res) {
if (res.checkResult.chooseImage) {
wx.chooseImage({
count: 1,
sizeType: ['compressed'],
sourceType: ['album', 'camera'],
success: function(req) {
wx.getLocalImgData({
localId: req.localIds[0].toString(),
success: function (res) {
const localData = res.localData;
let imageBase64 = '';
if (localData.indexOf('data:image') == 0) {
//苹果的直接赋值,默认生成'data:image/jpeg;base64,'的头部拼接
imageBase64 = localData;
} else {
//此处是安卓中的唯一得坑!在拼接前需要对localData进行换行符的全局替换
//此时一个正常的base64图片路径就完美生成赋值到img的src中了
imageBase64 = 'data:image/jpeg;base64,' + localData.replace(/\n/g, '');
}
that.avatarUrl = imageBase64;
that.handleAvatar(that.dataURLtoBlob(imageBase64));
}
});
},
fail() {
that.$toast.show({
type: 'text',
text: '选择头像失败!',
});
}
});
} else {
that.$toast.show({
type: 'text',
text: '暂不支持修改头像!',
});
}
},
fail: function() {
that.$toast.show({
type: 'text',
text: '暂不支持修改头像!',
});
},
});
} else {
that.lgBridgeChooseImage();
}
});
} else {
that.lgBridgeChooseImage();
}
},
handleAvatar(imageData) {
let that = this;
let param = new FormData();
param.append('headPic', imageData);
that.$http.post('/upload.json', {
headers: {
'Content-Type': 'multipart/form-data',
},
params: param,
}).then(res => {
if (parseInt(res.state, 10) === 1) {
that.$toast.show({
type: 'success',
text: '上传成功!',
});
that.avatarUrl = res.content && res.content.data && res.content.data.url;
}
});
},
dataURLtoBlob(dataurl) {
let arr = dataurl.split(',');
let mime = arr[0].match(/:(.*?);/)[1];
let bstr = atob(arr[1]);
let n = bstr.length;
let u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], { type: mime });
}
}
};
</script>
<style lang="less" scoped>
.card-avatar {
position: absolute;
top: 0;
left: 50%;
transform: translate(-50%, -50%);
width: 180px;
height: 180px;
border-radius: 100%;
overflow: hidden;
img {
width: 100%;
height: 100%;
}
.choose-image, input {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0;
}
}
</style>
Я ссылался на много статей по этому требованию.На самом деле большинство из них наполовину поняты.У всех разные проблемы.Эта статья можно сказать полностью решена.wx.chooseImage
Все виды неизлечимых болезней, один шаг, так что воспользуйтесь сегодняшним отдыхом, чтобы записать весь процесс и поделиться им со всеми нуждающимися коллегами в будущем!
Замечательный превью: Большой спрос, который длился два месяца, недавно столкнулся со многими подводными камнями, и я буду делиться ими один за другим в будущем, чтобы подбодрить друг друга 😂
Для более интересного контента, пожалуйста, обратите внимание на мой паблик [Небесные награды за усердие Льюис]