HarmonyOS鸿蒙Next中在弹窗中保存网络图片Permission denied, js errcode:201
HarmonyOS鸿蒙Next中在弹窗中保存网络图片Permission denied, js errcode:201
static async loadImageWithUrl(context:Context,url: string): Promise<boolean> {
let pixelMaptemp: PixelMap | undefined = undefined;
let responseCode = http.ResponseCode;
let OutData: http.HttpResponse;
let imagePackerApi = image.createImagePacker();
let packOpts: image.PackingOption = { format: 'image/jpeg', quality: 100 };
// 确保网络正常
http.createHttp().request(url, {
method: http.RequestMethod.GET,
connectTimeout: 60000,
readTimeout: 60000
},
async (error: BusinessError, data: http.HttpResponse) => {
if (error) {
console.error(`http request failed with. Code: ${error.code}, message: ${error.message}`);
} else {
OutData = data;
let code: http.ResponseCode | number = OutData.responseCode;
if (responseCode.OK === code) {
let imageData: ArrayBuffer = OutData.result as ArrayBuffer;
let imageSource: image.ImageSource = image.createImageSource(imageData);
class tmp {
height: number = 100
width: number = 100
};
let options: Record<string, number | boolean | tmp> = {
'alphaType': 0, // Transparency
'editable': false, // Is it editable
'pixelFormat': 3, // Pixel Format
'scaleMode': 1, // Abbreviation
'size': { height: 100, width: 100 }
}; // Create Image Size
imageSource.createPixelMap(options).then((pixelMap: PixelMap) => {
pixelMaptemp = pixelMap;
pixelMaptemp.getImageInfo().then((info: image.ImageInfo) => {
console.info('info.width = ' + info.size.width);
}).catch((err: BusinessError) => {
console.error('Failed ' + err);
})
imagePackerApi.packToData(pixelMaptemp, packOpts).then(async (buffer: ArrayBuffer) => {
try {
let helper = photoAccessHelper.getPhotoAccessHelper(context);
let uri = await helper.createAsset(photoAccessHelper.PhotoType.IMAGE, 'png');
let file = await fs.open(uri, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
// Write to file
await fs.write(file.fd, buffer);
promptAction.openToast({
message: '已保存至相册',
duration: 2500
});
// Close the file
await fs.close(file.fd);
} catch (error) {
console.error('error is ' + JSON.stringify(error));
}
return false
}).catch((error: BusinessError) => {
console.error('Failed to pack the image. And the error is: ' + error);
}).finally(()=>{
pixelMap.release();
})
})
}
}
}
)
return false
}
以上是保存图片的方法
@CustomDialog
@Component
struct CustomDialogExample {
@Prop smallPic: string;
@Prop bigPic: string;
@Prop context: Context;
controller?: CustomDialogController;
build() {
Stack({ alignContent: Alignment.Bottom }) {
Image(this.smallPic)
.width('100%')
.height("100%")
Button("保存到相册", { type: ButtonType.Normal, stateEffect: true })
.onClick(async ()=>{
await FilesUtils.loadImageWithUrl(this.context,this.bigPic).then((result)=>{
if (result) {
this.controller?.close()
}
});
})
.borderRadius(8)
.backgroundColor(0x317aff)
}.borderRadius(10).height(300)
}
}
以上是弹窗代码
dialogController: CustomDialogController | null = new CustomDialogController({
builder: CustomDialogExample({
smallPic: this.datepicBean[0].smallPic,
bigPic: this.datepicBean[0].bigPic,
context:this.context
}),
autoCancel: true,
onWillDismiss: (dismissDialogAction: DismissDialogAction) => {
console.info(`reason= ${dismissDialogAction.reason}`);
console.info('dialog onWillDismiss');
if (dismissDialogAction.reason == DismissReason.PRESS_BACK) {
dismissDialogAction.dismiss();
}
if (dismissDialogAction.reason == DismissReason.TOUCH_OUTSIDE) {
dismissDialogAction.dismiss();
}
},
alignment: DialogAlignment.Bottom,
offset: { dx: 0, dy: -20 },
gridCount: 4,
customStyle: false,
cornerRadius: 10,
})
以上是弹窗Controller,context为:
private context = this.getUIContext().getHostContext()!;
现在是在弹窗中保存图片就提示Permission denied, js errcode:201,如果不在弹窗中调用loadImageWithUrl就能正常保存图片,请问这个context该怎么传?
更多关于HarmonyOS鸿蒙Next中在弹窗中保存网络图片Permission denied, js errcode:201的实战教程也可以访问 https://www.itying.com/category-93-b0.html
你当前通过 this.getUIContext().getHostContext() 获取的是 HostContext(UI 层上下文),而相册读写、文件操作等权限相关操作必须依赖具备完整权限能力的 AbilityContext(应用能力上下文),这是导致权限拒绝的根本原因。
更多关于HarmonyOS鸿蒙Next中在弹窗中保存网络图片Permission denied, js errcode:201的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
感谢,private context = this.getUIContext().getHostContext() as common.UIAbilityContext; 这样就都可以了,
在HarmonyOS Next中,弹窗内保存网络图片出现Permission denied,错误码201,通常是由于未正确配置存储权限所致。需要在module.json5文件的module字段内,添加ohos.permission.WRITE_IMAGEVIDEO权限请求。同时,确保在保存操作前,通过系统能力接口动态申请该权限。
在HarmonyOS Next中,弹窗(CustomDialog)是一个独立的UI组件,其生命周期和上下文环境与主页面不同。你遇到的Permission denied, js errcode:201错误,通常是因为在弹窗中使用的context没有正确的权限或上下文环境。
从你的代码看,你通过this.getUIContext().getHostContext()获取了context并传递给弹窗。但在弹窗中,这个context可能无法正确访问相册等敏感资源。
解决方案:
-
直接使用弹窗自身的
context在弹窗组件内部,可以直接使用ArkUI提供的getContext()方法获取正确的上下文:[@CustomDialog](/user/CustomDialog) [@Component](/user/Component) struct CustomDialogExample { // 移除@Prop context: Context; controller?: CustomDialogController; aboutToAppear() { // 可以在生命周期中获取context let context = getContext(); } build() { // ... .onClick(async ()=>{ let context = getContext(); // 在这里获取 await FilesUtils.loadImageWithUrl(context, this.bigPic).then((result)=>{ // ... }); }) } } -
在调用弹窗时传递UI上下文 如果需要在弹窗构建时传递,可以使用正确的上下文获取方式:
// 在主页面中 private context = getContext(); // 使用getContext()而不是getUIContext().getHostContext() // 或者直接在构建弹窗时获取 dialogController: CustomDialogController | null = new CustomDialogController({ builder: CustomDialogExample({ smallPic: this.datepicBean[0].smallPic, bigPic: this.datepicBean[0].bigPic, context: getContext() // 直接使用getContext() }), // ... 其他配置 }) -
确保权限声明 在
module.json5中确认已声明必要的权限:{ "module": { "requestPermissions": [ { "name": "ohos.permission.READ_IMAGEVIDEO", "reason": "$string:reason_desc", "usedScene": { "abilities": ["EntryAbility"], "when": "always" } }, { "name": "ohos.permission.WRITE_IMAGEVIDEO", "reason": "$string:reason_desc", "usedScene": { "abilities": ["EntryAbility"], "when": "always" } } ] } }
关键点:
- 弹窗中的上下文环境是独立的,不能直接使用主页面的上下文对象
getContext()在ArkUI中会自动返回当前组件可用的正确上下文- 权限错误201通常表示上下文环境不正确或权限未正确声明
建议在弹窗内部使用getContext()动态获取上下文,这样可以确保始终使用正确的上下文环境来访问相册等系统资源。

