Native保存图片到应用沙箱

本示例主要介绍Native如何将网络上的图片及Rawfile中的图片保存到应用沙箱中。

效果图

使用说明

1.rawfile路径下存有一张图片sandBoxTest.jpg。

2.设备连接上网络。

3.点击"保存Rawfile图片",前端通过调用Native侧暴露的saveImageOfRawfileCallback接口将rawfile中的图片sandBoxTest.jpg保存到应用沙箱中并返回沙箱路径到前端进行显示;点击“保存网络图片”,前端通过调用Native侧暴露的saveImageOfInternetCallback接口将网络图片https://gitee.com/harmonyos-cases/cases/raw/master/CommonAppDevelopment/feature/imagedepthcopy/src/main/resources/rawfile/depthCopy.png保存到应用沙箱中并返回沙箱路径到前端进行显示。 具体代码可参考NativePictureToSandboxView.ets以及native_picture_to_sandbox.cpp。

实现思路

Native保存网络图片到沙箱的实现主要步骤如下:

1.参考libcurl编译,编译libcurl.so等相关库文件。当前编译后加载libcurl.so时,通过hilog日志发现依赖了libcurl.so libcurl.so.4 libnghttp2.so libnghttp2.so.14 libzstd.so几个so文件。其中libcurl.so为开源的跨平台网络协议库,支持七层网络模型中应用层的各种协议;libnghttp2.so是一个HTTP/2和SPDY协议的实现,用于客户端,服务器,代理,和服务器推送应用;libzstd.so是一个实现了Zstandard算法的压缩库,常用于数据库、文件系统及网络传输等

2.将开源库libcurl相关的so文件以及封装了libcurl下载功能的libcurlDownload.so放入模块下的libs相应目录。

3.在CMakeLists中导入相关库文件。

target_link_directories(nativesavepictosandbox PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/${OHOS_ARCH}/) 
target_link_libraries(nativesavepictosandbox PUBLIC libace_napi.z.so libcurlDownload.so libhilog_ndk.z.so librawfile.z.so)

4.在前端通过调用Native中的saveImageOfInternetCallback接口获取沙箱地址并将沙箱地址转换为url地址绑定到Image组件显示。传入的参数为网络图片地址、应用的文件路径、沙箱中的文件名。

5.在Native的saveImageOfInternetCallback接口中通过调用libcurlDownload.so的接口将网络图片写入沙箱。

// TODO:知识点:使用dlopen动态加载so库,返回so库的句柄 
void *handler = dlopen(libCurlDownload, RTLD_LAZY); 
if (handler == nullptr) { 
    // 抛出加载库失败的错误 
    dlerror(); 
    return; 
} 
 
// 声明函数指针类型 
typedef std::string (*DownloadInternetFileFunc)(char *, char *); 
DownloadInternetFileFunc downloadInternetWrapper = 
    reinterpret_cast<DownloadInternetFileFunc>(dlsym(handler, "DownloadInternetFileWrapper")); 
if (downloadInternetWrapper) { 
    // TODO:知识点:调用so的downloadInternetWrapper函数保存网路图片到沙箱 
    CallbackInternetContext *internetContext = (CallbackInternetContext *)data; 
    if (internetContext == nullptr) { 
        OH_LOG_Print(LOG_APP, LOG_ERROR, GLOBAL_RESMGR, TAG, "saveImageOfInternet internetContext is null"); 
        return; 
    } 
    // 图片沙箱完整路径 
    std::string targetSandboxPath = internetContext->sandboxDir + internetContext->FileName; 
    OH_LOG_Print(LOG_APP, LOG_INFO, GLOBAL_RESMGR, TAG, "saveImageOfInternet 保存沙箱文件:%{public}s", 
        targetSandboxPath.c_str()); 
 
    internetContext->result = downloadInternetWrapper((char *)internetContext->internetPicUrl.c_str(), 
    (char *)targetSandboxPath.c_str()); 
    OH_LOG_Print(LOG_APP, LOG_INFO, GLOBAL_RESMGR, TAG, "saveImageOfInternet download finish"); 
    dlclose(handler); 
} else { 
    OH_LOG_Print(LOG_APP, LOG_ERROR, GLOBAL_RESMGR, TAG, "saveImageOfInternet download function is null"); 
    dlclose(handler); 
}

Native保存Rawfile图片到沙箱的实现主要步骤如下:

1.在前端通过调用Native中的saveImageOfRawfileCallback接口获取沙箱地址并将沙箱地址转换为url地址绑定到Image组件显示。传入的参数为js的资源对象、rawfile中的图片名、应用的文件路径。

Button($r('app.string.tbn_RawFilePicture')) 
    .onClick(() => { 
        // TODO:知识点:通过Native暴露的接口saveImageOfRawfileCallback接口获取rawfile中图片保存在沙箱中的路径 
        testNapi.saveImageOfRawfileCallback(this.resMgr, this.rawfilePicPath, this.fileDir, ((result: string) => { 
            if (result === undefined || result === '') { 
                AlertDialog.show({ 
                    message: $r('app.string.rawfile_write_fail'), 
                    alignment: DialogAlignment.Center 
                }); 
                this.rawfileSandBoxPath = ''; 
            } else { 
                this.rawfileSandBoxPath = fileUri.getUriFromPath(result); 
                logger.info('[pic2sandbox]', `saveImageOfRawfile sandboxPath is ` + result); 
            } 
        })) 
    })

2.在Native的saveImageOfRawfileCallback接口中通过Rawfile的API接口以及文件流将图片资源写入沙箱。

// 打开Rawfile文件。 
RawFile *rawFile = OH_ResourceManager_OpenRawFile(rawFileContext->resMgr, 
    rawFileContext->rawFileName.c_str()); 
if (rawFile == nullptr) { 
    OH_LOG_Print(LOG_APP, LOG_ERROR, GLOBAL_RESMGR, TAG, "saveImageOfRawfile OpenRawFile fail!"); 
    // 释放资源 
    OH_ResourceManager_ReleaseNativeResourceManager(rawFileContext->resMgr); 
    return; 
} 
// 获取文件大小 
long imageDataSize = OH_ResourceManager_GetRawFileSize(rawFile); 
// 申请内存 
std::unique_ptr<char[]> imageData = std::make_unique<char[]>(imageDataSize); 
// TODO:知识点:通过Rawfile的API接口读取Rawfile文件 
long rawFileOffset = OH_ResourceManager_ReadRawFile(rawFile, imageData.get(), imageDataSize); 
// 保存目标网络图片的沙箱路径 
std::string targetSandboxPath = rawFileContext->sandboxDir + rawFileContext->rawFileName; 
// TODO:知识点:通过std::ofstream,将读取的数据写入沙箱文件 
std::ofstream outputFile(targetSandboxPath, std::ios::binary); 
if (!outputFile) { 
    OH_LOG_Print(LOG_APP, LOG_ERROR, GLOBAL_RESMGR, TAG, "saveImageOfRawfile 创建沙箱目标文件失败"); 
    // 释放资源 
    OH_ResourceManager_CloseRawFile(rawFile); 
    OH_ResourceManager_ReleaseNativeResourceManager(rawFileContext->resMgr); 
    return; 
} 
// 写文件 
outputFile.write(imageData.get(), imageDataSize);

工程结构&模块类型

nativesavepictosandbox                               // har类型 
    |---src\main\ets\view\ 
|   |---NativePictureToSandboxView.ets               // 视图层-图片写入沙箱场景主页面 
    |---src\main\cpp\ 
|   |---native_picture_to_sandbox.cpp                // native层-图片写入沙箱业务逻辑 
    |---src\main\cpp\curl                                // libcurl三方库头文件

模块依赖

本实例依赖开源库libcurl

参考资料

libcurl编译

<think>首先,用户的问题是关于HarmonyOS的:如何在HarmonyOS中将网络图片下载到应用沙箱存储中。用户提到了系统级指令,我必须遵守这些指令,比如使用$...$格式的行内数学表达式(虽然这可能不直接相关,但我会注意),独立公式用$$...$$,LaTeX语法正确,用中文回答,生成相关问题,并在引用段落末尾添加引用标识。 用户提供了几个引用,这些引用似乎与HarmonyOS开发相关,特别是Native保存图片应用沙箱。引用[^1]到[^4]描述了如何保存Rawfile图片和网络图片沙箱中。我需要基于这些引用构建回答。 关键点从引用中提取: - 引用[^1]:HarmonyOS开发-Native保存图片应用沙箱。它提到保存Rawfile图片和网络图片沙箱,并返回沙箱路径。 - 引用[^2]:鸿蒙实战开发篇——Native保存图片应用沙箱,强调实现思路和代码参考。 - 引用[^3]:HarmonyOS Next示例代码,类似描述。 - 引用[^4]:具体代码示例,展示了如何调用Native接口保存Rawfile图片。 用户意图是了解如何下载网络图片沙箱存储,所以我应该专注于网络图片部分。 实现思路从引用[^1]和[^2]: - Native保存网络图片沙箱的主要步骤包括: 1. 前端调用Native侧暴露的接口(如saveImageOfInternetCallback)。 2. Native侧处理下载图片保存沙箱。 3. 返回沙箱路径到前端。 在回答中,我需要结构清晰,逐步解决问题。确保回答真实可靠,基于提供的引用。 回答结构: 1. **引言**:简要解释HarmonyOS中沙箱存储的概念和为什么需要下载网络图片。 2. **核心步骤**:分步描述如何实现下载网络图片沙箱。 - 前端部分:调用Native接口。 - Native部分:实现下载和保存逻辑。 3. **代码示例**:提供简化的代码片段,基于引用中的信息。 4. **注意事项**:提到网络权限、错误处理等。 5. **生成相关问题**:在末尾添加相关问题。 使用中文回答。 生成相关问题:基于主题,提出几个相关问题,如优化、性能分析等。 引用标识:在引用段落末尾添加[^n],但引用是用户提供的,所以我需要引用这些引用。例如,当提到步骤时,引用[^1]。 现在,构建回答大纲: - 开头:解释HarmonyOS应用沙箱。 - 步骤1:前端调用Native接口。 - 步骤2:Native实现下载和保存。 - 代码示例:简化版。 - 结尾:总结和注意事项。 - 相关问题。 确保LaTeX正确:如果有数学表达式,但这里可能没有,所以或许不需要。 最后,添加相关问题。</think>### HarmonyOS 下载网络图片应用沙箱存储的实现方法 在HarmonyOS开发中,应用沙箱(Sandbox)是一种安全隔离的存储空间,每个应用只能访问自己的沙箱目录,防止数据泄露或被篡改。将网络图片下载到沙箱存储是常见需求,例如缓存图片或离线使用。基于引用中的实现思路[^1][^2],以下是详细步骤和代码示例。整个过程分为前端(ArkTS/JS)和Native(C++)两部分,前端负责调用接口,Native处理下载和存储逻辑。 #### 核心步骤 1. **前端调用Native接口**: - 在ArkTS/UI中,通过`Button`组件触发下载操作。 - 调用Native侧暴露的接口(如`saveImageOfInternetCallback`),传入网络图片URL和目标沙箱路径。 - 处理返回的沙箱路径,用于前端显示或后续操作。参考引用[^1][^3],需确保设备已联网。 2. **Native实现下载和保存**: - **下载图片**:使用libcurl或鸿蒙的`OH_NetConn`模块发起HTTP请求,获取图片数据流。 - **保存沙箱**:将数据流写入应用沙箱目录(如`/data/storage/el2/base/files/`),使用文件I/O操作(如`fopen`、`fwrite`)。 - **返回路径**:将沙箱文件路径返回给前端。需处理网络错误和文件写入失败(如权限不足或存储空间不足)[^1][^4]。 3. **权限和配置**: - 在`module.json5`中添加网络权限:`"requestPermissions": [{"name": "ohos.permission.INTERNET"}]`。 - 沙箱目录需通过`@ohos.file.fs`或Native API访问,确保路径正确[^2][^4]。 #### 代码示例 以下是一个简化版实现(基于HarmonyOS Next),完整代码可参考引用[^2][^3]。 **前端(ArkTS)**: ```typescript import testNapi from 'libentry.so'; // Native模块 import fileUri from '@ohos.file.fs'; // 文件路径处理 // 点击按钮下载网络图片 Button($r('app.string.btn_DownloadInternetImage')) .onClick(() => { const imageUrl = "https://example.com/image.png"; // 替换为实际URL const saveDir = "/data/storage/el2/base/files/"; // 沙箱目录 // 调用Native接口 const sandBoxPath: string = testNapi.saveImageOfInternetCallback(imageUrl, saveDir); if (!sandBoxPath) { console.error("下载失败"); } else { const displayPath = fileUri.getUriFromPath(sandBoxPath); // 转换路径 console.log("图片保存路径: " + displayPath); } }); ``` **Native(C++)**: ```cpp #include <curl/curl.h> // 使用libcurl下载 #include <fstream> #include <string> // 回调函数处理下载数据 static size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp) { std::vector<char>* buffer = static_cast<std::vector<char>*>(userp); size_t total = size * nmemb; buffer->insert(buffer->end(), static_cast<char*>(contents), static_cast<char*>(contents) + total); return total; } // 暴露给前端的接口 napi_value SaveImageOfInternetCallback(napi_env env, napi_callback_info info) { // 解析参数:URL和沙箱目录 napi_value args[2]; size_t argc = 2; napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); char url[256], dirPath[256]; napi_get_value_string_utf8(env, args[0], url, sizeof(url), nullptr); napi_get_value_string_utf8(env, args[1], dirPath, sizeof(dirPath), nullptr); // 下载图片 std::vector<char> imageData; CURL* curl = curl_easy_init(); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &imageData); CURLcode res = curl_easy_perform(curl); if (res != CURLE_OK) { curl_easy_cleanup(curl); return nullptr; // 下载失败 } curl_easy_cleanup(curl); // 保存沙箱 std::string filePath = std::string(dirPath) + "downloaded_image.jpg"; std::ofstream outFile(filePath, std::ios::binary); if (!outFile.is_open()) { return nullptr; // 文件写入失败 } outFile.write(imageData.data(), imageData.size()); outFile.close(); // 返回沙箱路径 napi_value result; napi_create_string_utf8(env, filePath.c_str(), NAPI_AUTO_LENGTH, &result); return result; } ``` #### 注意事项 1. **错误处理**:添加`try-catch`块或检查返回值,避免网络超时或无效URL导致崩溃[^4]。 2. **性能优化**:大图片下载时使用分块传输或异步任务,防止UI阻塞[^3]。 3. **安全风险**:验证URL来源,防止恶意文件注入。 4. **存储管理**:定期清理沙箱文件,避免空间不足。引用中的示例表明,沙箱路径需通过`fileUri.getUriFromPath`转换才能在UI显示[^4]。 通过以上步骤,您可以在HarmonyOS应用中高效下载网络图片沙箱存储。实际开发时,请参考官方文档和示例代码[^2][^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值