在鸿蒙(HarmonyOS)中从本地图库选择并上传图片,主要涉及 文件选择器(Picker) 和 网络请求(HTTP) 两个核心模块。以下是详细步骤和代码示例(基于 ArkTS/JS 开发):
1. 添加权限
在 module.json5
中声明必要权限:
json
{
"module": {
"requestPermissions": [
{
"name": "ohos.permission.READ_MEDIA" // 读取本地媒体文件
},
{
"name": "ohos.permission.INTERNET" // 网络访问
}
]
}
}
2. 使用文件选择器(Picker)选择图片
鸿蒙提供了 PhotoViewPicker
从图库中选择图片:
javascript
import picker from '@ohos.file.picker';
import fs from '@ohos.file.fs';
async function selectImageFromGallery(): Promise<string | undefined> {
try {
// 1. 创建图片选择器
const photoSelectOptions: picker.PhotoSelectOptions = {
MIMEType: picker.PhotoViewMIMETypes.IMAGE_TYPE, // 仅选择图片
maxSelectNumber: 1, // 选择1张图片
};
const photoPicker = new picker.PhotoViewPicker();
const result = await photoPicker.select(photoSelectOptions);
// 2. 返回选择的图片URI(如:file://media/images/1.jpg)
if (result && result.photoUris.length > 0) {
return result.photoUris[0];
}
} catch (error) {
console.error('选择图片失败:', error);
}
return undefined;
}
3. 将图片转换为可上传的格式
鸿蒙的 PhotoViewPicker
返回的 URI 不能直接用于上传,需通过 fileIO
或 fs
模块读取文件内容:
javascript
async function readFileData(uri: string): Promise<Uint8Array | undefined> {
try {
// 1. 将URI转换为实际路径(如:file:// -> /data/media/images/1.jpg)
const filePath = uri.replace('file://', '');
// 2. 读取文件二进制数据
const file = fs.openSync(filePath, fs.OpenMode.READ_ONLY);
const fileData = fs.readSync(file.fd);
fs.closeSync(file);
return fileData;
} catch (error) {
console.error('读取文件失败:', error);
}
return undefined;
}
4. 上传图片到服务器
使用 @ohos.net.http
发送 multipart/form-data
请求:
javascript
import http from '@ohos.net.http';
async function uploadImage(fileData: Uint8Array, fileName: string): Promise<void> {
const httpRequest = http.createHttp();
// 1. 构造表单数据
const formData = new FormData();
formData.append('file', new Blob([fileData]), fileName);
// 2. 发送请求
const options = {
method: 'POST',
url: 'https://your-server.com/upload', // 替换为实际API地址
header: {
'Content-Type': 'multipart/form-data',
},
extraData: formData,
};
try {
const response = await httpRequest.request(options);
if (response.responseCode === 200) {
console.info('上传成功:', response.result);
} else {
console.error('上传失败:', response.responseCode);
}
} catch (error) {
console.error('网络请求错误:', error);
}
}
5. 完整流程整合
在页面中绑定按钮点击事件,串联整个流程:
typescript
import common from '@ohos.app.ability.common';
@Entry
@Component
struct ImageUploadPage {
@State previewImage: string = ''; // 预览图片路径
async onUploadClick() {
// 1. 从图库选择图片
const imageUri = await selectImageFromGallery();
if (!imageUri) return;
// 2. 预览图片
this.previewImage = imageUri;
// 3. 读取文件数据
const fileData = await readFileData(imageUri);
if (!fileData) return;
// 4. 上传(文件名取时间戳)
const fileName = `image_${new Date().getTime()}.jpg`;
await uploadImage(fileData, fileName);
}
build() {
Column() {
// 图片预览
if (this.previewImage) {
Image(this.previewImage)
.width(300)
.height(300)
}
// 上传按钮
Button('选择并上传图片')
.onClick(() => this.onUploadClick())
}
.width('100%')
.height('100%')
}
}
关键注意事项
-
动态权限申请 :
首次访问图库时需动态申请
READ_MEDIA
权限:javascriptimport abilityAccessCtrl from '@ohos.abilityAccessCtrl'; async function requestPermissions() { const permissions: Array<string> = ['ohos.permission.READ_MEDIA']; const atManager = abilityAccessCtrl.createAtManager(); await atManager.requestPermissionsFromUser(getContext(), permissions); }
-
URI转换问题:
- 鸿蒙返回的URI可能是
internal://media/images/1
,需通过@ohos.file.fs
转换为可读路径。 - 使用
fs.openSync
时需确保路径合法。
- 鸿蒙返回的URI可能是
-
服务器兼容性:
- 确保服务器支持
multipart/form-data
格式。 - 若需HTTPS,需在
config.json
中配置网络安全策略。
- 确保服务器支持