You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Xamarin Android中如何将图片保存到用户选择的目录

解决通过SAF选中目录保存Bitmap的问题

核心问题在于:SAF(存储访问框架)返回的Uri并非真实的本地文件系统路径,你不能直接通过File类或FileOutputStream访问这些Uri对应的文件,必须通过ContentResolver来操作文件流。

修正后的代码实现

替换你尝试的写文件代码,改用ContentResolver打开输出流直接写入Bitmap:

// 创建目标文件
DocumentFile docFile = documentFile.CreateFile("image/png", fileName);
if (docFile == null) {
    Toast.MakeText(this, "无法创建目标文件", ToastLength.Short).Show();
    return;
}

// 通过ContentResolver获取输出流,直接写入Bitmap
try (OutputStream outputStream = ContentResolver.OpenOutputStream(docFile.Uri)) {
    // 直接压缩Bitmap到输出流,无需中转字节数组,更高效
    imageBitmap.Compress(Bitmap.CompressFormat.Png, 100, outputStream);
    outputStream.Flush();
    Toast.MakeText(this, "图片保存成功", ToastLength.Short).Show();
} catch (Java.IO.IOException e) {
    Android.App.AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.SetTitle("错误");
    builder.SetMessage(e.Message);
    builder.SetNeutralButton("确定", (o, args) => {});
    builder.Show();
}

错误原因说明

  1. SAF返回的Uri(如content://com.android.providers.downloads.documents/tree/primary:Music/...)是系统文档提供器的抽象路径,并非磁盘上的真实文件路径。你之前获取的docFile.Uri.Path只是Uri的路径片段,不能直接用来创建File对象。
  2. Android 10及以上的分区存储机制,限制了应用直接访问外部存储的文件路径,必须通过SAF的内容提供器接口来操作文件。

完整修正后的SaveImage方法参考

private void SaveImage(Uri uri, string fileName) {
    var imageBitmap = Bitmap.CreateBitmap(pictureBox1.Width, pictureBox1.Height, Bitmap.Config.Argb8888);
    if (uri.Scheme.Equals("content")) {
        try {
            Context applicationContext = Application.Context;
            DocumentFile documentFile = DocumentFile.FromTreeUri(applicationContext, uri);
            if (documentFile != null && documentFile.Exists() && documentFile.IsDirectory) {
                // 创建目标文件
                DocumentFile docFile = documentFile.CreateFile("image/png", fileName);
                if (docFile == null) {
                    Toast.MakeText(this, "无法创建目标文件", ToastLength.Short).Show();
                    return;
                }

                // 写入Bitmap
                try (OutputStream outputStream = ContentResolver.OpenOutputStream(docFile.Uri)) {
                    imageBitmap.Compress(Bitmap.CompressFormat.Png, 100, outputStream);
                    outputStream.Flush();
                    Toast.MakeText(this, "图片保存成功", ToastLength.Short).Show();
                } catch (Java.IO.IOException e) {
                    Android.App.AlertDialog.Builder builder = new AlertDialog.Builder(this);
                    builder.SetTitle("错误");
                    builder.SetMessage(e.Message);
                    builder.SetNeutralButton("确定", (o, args) => {});
                    builder.Show();
                }
            }
        } catch (Exception ex) {
            Log.Debug("SaveImageError", ex.Message);
            Toast.MakeText(this, "保存失败:" + ex.Message, ToastLength.Long).Show();
        }
    }
}

内容的提问来源于stack exchange,提问作者user23633404

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 09:19:56