我有一个 Xamarin 表单应用程序,我想保存文件,当用户在手机中打开文件管理器或手机连接到计算机时,应该显示该文件。我读了这篇文章,但问题是文件存储到
Environment.SpecialFolder.Personal
,用户无法打开这个路径。我还发现了这个plugin,它的作用完全相同。它将文件存储到路径Environment.SpecialFolder.Personal
。当我尝试将文件保存在另一个位置时,我总是收到错误消息:
访问路径“..”被拒绝
我应该使用哪个路径来保存文件?
类型映射到路径System.Environment.SpecialFolder.Personal
。这是您的应用程序的私有目录,因此您将无法使用文件浏览器查看这些文件,除非它具有 root 权限。/data/data/[your.package.name]/files
所以如果你想让文件被用户找到,你不能将文件保存在
Personal
文件夹中,而是保存在其他文件夹中(如Downloads
):
string directory = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.AbsolutePath, Android.OS.Environment.DirectoryDownloads);
string file = Path.Combine(directory, "yourfile.txt");
您还必须向
AndroidManifest.xml
添加权限:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
以下是为 Android、iOS 和 UWP 保存图像的代码:
安卓:
public void SaveImage(string filepath)
{
var imageData = System.IO.File.ReadAllBytes(filepath);
var dir = Android.OS.Environment.GetExternalStoragePublicDirectory(
Android.OS.Environment.DirectoryDcim);
var pictures = dir.AbsolutePath;
var filename = System.DateTime.Now.ToString("yyyyMMddHHmmssfff") + ".jpg";
var newFilepath = System.IO.Path.Combine(pictures, filename);
System.IO.File.WriteAllBytes(newFilepath, imageData);
//mediascan adds the saved image into the gallery
var mediaScanIntent = new Intent(Intent.ActionMediaScannerScanFile);
mediaScanIntent.SetData(Android.Net.Uri.FromFile(new Java.IO.File(newFilepath)));
Xamarin.Forms.Forms.Context.SendBroadcast(mediaScanIntent);
}
iOS:
public async void SaveImage(string filepath)
{
// First, check to see if we have initially asked the user for permission
// to access their photo album.
if (Photos.PHPhotoLibrary.AuthorizationStatus ==
Photos.PHAuthorizationStatus.NotDetermined)
{
var status =
await Plugin.Permissions.CrossPermissions.Current.RequestPermissionsAsync(
Plugin.Permissions.Abstractions.Permission.Photos);
}
if (Photos.PHPhotoLibrary.AuthorizationStatus ==
Photos.PHAuthorizationStatus.Authorized)
{
// We have permission to access their photo album,
// so we can go ahead and save the image.
var imageData = System.IO.File.ReadAllBytes(filepath);
var myImage = new UIImage(NSData.FromArray(imageData));
myImage.SaveToPhotosAlbum((image, error) =>
{
if (error != null)
System.Diagnostics.Debug.WriteLine(error.ToString());
});
}
}
请注意,对于 iOS,我使用 Plugin.Permissions nuget 数据包来请求用户的权限。
UWP:
public async void SaveImage(string filepath)
{
var imageData = System.IO.File.ReadAllBytes(filepath);
var filename = System.DateTime.Now.ToString("yyyyMMddHHmmssfff") + ".jpg";
if (Device.Idiom == TargetIdiom.Desktop)
{
var savePicker = new Windows.Storage.Pickers.FileSavePicker();
savePicker.SuggestedStartLocation =
Windows.Storage.Pickers.PickerLocationId.PicturesLibrary;
savePicker.SuggestedFileName = filename;
savePicker.FileTypeChoices.Add("JPEG Image", new List<string>() { ".jpg" });
var file = await savePicker.PickSaveFileAsync();
if (file != null)
{
CachedFileManager.DeferUpdates(file);
await FileIO.WriteBytesAsync(file, imageData);
var status = await CachedFileManager.CompleteUpdatesAsync(file);
if (status == Windows.Storage.Provider.FileUpdateStatus.Complete)
System.Diagnostics.Debug.WriteLine("Saved successfully"));
}
}
else
{
StorageFolder storageFolder = KnownFolders.SavedPictures;
StorageFile sampleFile = await storageFolder.CreateFileAsync(
filename + ".jpg", CreationCollisionOption.ReplaceExisting);
await FileIO.WriteBytesAsync(sampleFile, imageData);
}
}
对于 Android,@David Moškoř 的答案非常有效。
对于IOS,我们可以使用以下路径:
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "..", "Library");
但是必须在IOS项目的
LSSupportsOpeningDocumentsInPlace
文件中启用Supports Document Browser
和Info.plist
才能让用户浏览保存的文件(当您打开Files
应用程序并导航到On My iPhone
时会出现)
更新
在较新版本的IOS中,路径应该是:
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
在 info.plist 中:
<key>LSSupportsOpeningDocumentsInPlace</key>
<true/>
<key>UISupportsDocumentBrowser</key>
<true/>
<key>UIFileSharingEnabled</key>
<true/>