React-Native开发鸿蒙NEXT-图片上传
原创 悬空八只脚 悬空八只脚 2024年10月30日 10:11 江苏
之前在React-Native开发鸿蒙NEXT(5)
React-Native开发鸿蒙NEXT(5)
悬空八只脚,公众号:悬空八只脚React-Native开发鸿蒙NEXT(5)
里提到了鸿蒙下OSS上传的问题当时没有解决,后来解决了把这事忘记交代了,这里补充一下。后续关于React-Native开发鸿蒙NEXT一些技术输出不再以编号命名,基本会以技术点为标题便于查找,尽量多聊些干货
由于阿里云OSS没有HarmonyOS NEXT版本的SDK,只能使用web直传方式来实现RN端的图片上传,事实上阿里云对于HarmonyOS NEXT的最佳实践也是基于web直传来实现的。
(网址:
HarmonyOS NEXT的最佳实践help.aliyun.com/zh/oss/use-…
这里结合下实际项目来整体说明下图片上传流程。
图片的选取项目中使用的是react-native-image-picker
(网址:
react-native-image-pickerhttps://gitee.com/react-native-oh-library/usage-docs/blob/master/zh-cn/react-native-image-picker.md
实测发现如果相片高宽大于2000会出现报错的问题,最好限制一下尺寸
import {
launchImageLibrary,
launchCamera,
ImageLibraryOptions,
CameraOptions,
} from 'react-native-image-picker';
......
// 测试最高宽高2000就会报500错误,这里用1500
launchImageLibrary(
{
mediaType: 'photo',
maxWidth: 1500,
maxHeight: 1500,
quality: 1,
selectionLimit: 1,
},
.......
通过相机或者相片库返回的数据格式如下:
{
"assets": [{
"fileName": "screenshot_20240807_122206.jpg",
"type": "jpg",
"fileSize": 1467676,
"originalPath": "file://media/Photo/1/IMG_1723004626_000/screenshot_20240807_122206.jpg",
"height": 200,
"width": 200,
"uri": "/data/storage/el2/base/haps/entry/cache/rn_image_picker_lib_temp_a5421e0c-f687-4f76-9567-13147cc1a9bf.jpg"
}]
}
上传必须用到的字段是fileName和uri。项目中图片的上传是基于调用后台接口做的Form表单提交,这里列举下Form的结构,去除了项目相关的业务内容
import FS from 'react-native-fs';
//上传
export async function upload(uri: string, fileName: string) {
try {
const filecontent = await FS.readFile(uri, 'base64');
// convertBase64UrlToBlob(filecontent);
const body = new FormData();
// File64是后台业务定义的文件内容接收字段
body.append('File64', filecontent);
body.append('FileName', fileName);
const options = {
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data',
},
body,
};
const resp = await fetch(省略请求接口, options);
const text = await resp.text();
const json = JSON.parse(text);
// 如果请求失败
...省略业务异常
return json;
} catch (e) {
...省略异常处理
}
}
其中利用react-native-fs来根据uri获取文件内容。
(网址:
react-native-fshttps://gitee.com/react-native-oh-library/usage-docs/blob/master/zh-cn/react-native-fs.md
convertBase64UrlToBlob方法用来将获取到的base64格式文件内容转化为Blob,具体是否需要得看后台小伙伴的定义。网上查找到的资料转化后结果与基于在线转化的结果不一致,可以直接使用下面的方法。
function convertBase64UrlToBlob(base64: string) {
try {
let type = base64.split(',')[0].match(/:(.*?);/)[1];//提取base64头的type如 'image/png'
let bytes = atob(base64.split(',')[1]);//去掉url的头,并转换为byte (atob:编码 btoa:解码)
//处理异常,将ascii码小于0的转换为大于0
//let ab = new ArrayBuffer(bytes.length);//通用的、固定长度(bytes.length)的原始二进制数据缓冲区对象
let ia = new Uint8Array(bytes.length);
for (let i = 0; i < bytes.length; i++) {
ia[i] = bytes.charCodeAt(i);
}
let blob = new Blob([ia], {type: type});
// console.log(blob);
return blob;
} catch (e) {
...省略异常处理
}
}
建议将上传做成接口请求形式,避免暴露oss的accessKey和secret。
更多内容可关注
我的公众号悬空八只脚