如何从内存流获取图片路径?Xamarin.Forms PCL签名图存本地取路径
在Xamarin.Forms PCL中保存签名到本地并获取路径用于邮件附件
因为PCL项目无法直接访问平台特定的文件系统,所以我们需要借助Xamarin.Forms依赖服务来实现跨平台的文件保存逻辑。下面是完整的实现步骤:
1. 在PCL项目中定义存储服务接口
首先创建一个接口,统一定义保存签名的方法,这样各个平台可以实现自己的版本:
public interface ISignatureStorageService { // 传入签名字节数组,返回保存后的本地文件路径 Task<string> SaveSignatureAsync(byte[] signatureData); }
2. 为各平台实现存储服务
接下来在Android、iOS(以及UWP如果需要)项目中分别实现这个接口,处理平台特定的文件路径和保存逻辑:
Android平台实现
在Android项目中添加以下类,记得替换YourAppName.Droid为你的实际命名空间:
using System.IO; using System.Threading.Tasks; using Xamarin.Forms; [assembly: Dependency(typeof(SignatureStorageService))] namespace YourAppName.Droid { public class SignatureStorageService : ISignatureStorageService { public async Task<string> SaveSignatureAsync(byte[] signatureData) { // 获取应用私有文件目录,无需额外权限 var filePath = Path.Combine(Android.App.Application.Context.FilesDir.AbsolutePath, $"signature_{DateTime.Now:yyyyMMddHHmmss}.png"); using (var stream = new FileStream(filePath, FileMode.Create)) { await stream.WriteAsync(signatureData, 0, signatureData.Length); } return filePath; } } }
iOS平台实现
在iOS项目中添加以下类,替换YourAppName.iOS为你的实际命名空间:
using System.IO; using System.Threading.Tasks; using Foundation; using Xamarin.Forms; [assembly: Dependency(typeof(SignatureStorageService))] namespace YourAppName.iOS { public class SignatureStorageService : ISignatureStorageService { public async Task<string> SaveSignatureAsync(byte[] signatureData) { // 获取应用文档目录,私有且安全 var documentsPath = NSFileManager.DefaultManager.GetUrls(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomain.User)[0].Path; var filePath = Path.Combine(documentsPath, $"signature_{DateTime.Now:yyyyMMddHHmmss}.png"); using (var stream = new FileStream(filePath, FileMode.Create)) { await stream.WriteAsync(signatureData, 0, signatureData.Length); } return filePath; } } }
UWP平台实现(可选)
如果你的项目支持UWP,添加以下实现:
using System.IO; using System.Threading.Tasks; using Windows.Storage; using Xamarin.Forms; [assembly: Dependency(typeof(SignatureStorageService))] namespace YourAppName.UWP { public class SignatureStorageService : ISignatureStorageService { public async Task<string> SaveSignatureAsync(byte[] signatureData) { // 获取应用本地文件夹 var localFolder = ApplicationData.Current.LocalFolder; var file = await localFolder.CreateFileAsync($"signature_{DateTime.Now:yyyyMMddHHmmss}.png", CreationCollisionOption.ReplaceExisting); using (var stream = await file.OpenStreamForWriteAsync()) { await stream.WriteAsync(signatureData, 0, signatureData.Length); } return file.Path; } } }
3. 在PCL中调用服务并发送邮件
现在回到PCL项目,修改你的签名处理代码,调用依赖服务保存文件,然后用Cross-Messaging添加附件:
// 原有获取签名字节数组的代码 var imageStream = await signaturePad.GetImageStreamAsync(SignatureImageFormat.Png); var signatureMemoryStream = new MemoryStream(); await imageStream.CopyToAsync(signatureMemoryStream); // 建议用异步版本提高性能 byte[] data = signatureMemoryStream.ToArray(); // 通过依赖服务保存签名到本地,获取文件路径 var storageService = DependencyService.Get<ISignatureStorageService>(); string signatureFilePath = await storageService.SaveSignatureAsync(data); // 使用Cross-Messaging构建邮件并添加附件 var email = new EmailMessageBuilder() .To("recipient@example.com") .Subject("Attached Signature") .Body("Please find the signature attached below.") .AttachAttachment(signatureFilePath) .Build(); CrossMessaging.Current.EmailSender.SendEmail(email);
关键注意事项
- 我在文件名里加了时间戳,避免每次保存的签名覆盖之前的文件,你可以根据需求调整命名规则。
- 所有平台都是保存到应用私有目录,无需申请额外的文件访问权限,安全性更高。
- 确保每个平台的实现类都添加了
[assembly: Dependency(typeof(...))]属性,这样Xamarin.Forms才能正确解析服务。
内容的提问来源于stack exchange,提问作者Kartik Solanki
相关产品推荐
相关产品推荐

