Xamarin iOS端如何压缩FileResult以缩短Base64长度?
Xamarin iOS 头像图片压缩方案(解决Base64过长无法存入数据库问题)
方案一:使用SkiaSharp(跨平台推荐)
SkiaSharp是谷歌推出的跨平台图形库,适配Xamarin.Forms项目,能灵活控制图片尺寸与压缩质量,稳定性强。
操作步骤:
- 安装NuGet包:
SkiaSharp和SkiaSharp.Views.Forms - 修改你的
CapturePhoto方法如下:
using SkiaSharp; async Task CapturePhoto() { try { var result = await MediaPicker.CapturePhotoAsync(); if (result != null) { using (var stream = await result.OpenReadAsync()) using (var originalBitmap = SKBitmap.Decode(stream)) { // 定义目标头像宽度(可按需调整,200px足够满足大多数场景) int targetWidth = 200; // 按原比例计算目标高度,避免图片拉伸变形 int targetHeight = (int)((float)originalBitmap.Height / originalBitmap.Width * targetWidth); targetHeight = targetHeight == 0 ? targetWidth : targetHeight; // 缩放图片,平衡清晰度与性能 using (var resizedBitmap = originalBitmap.Resize(new SKImageInfo(targetWidth, targetHeight), SKFilterQuality.Medium)) using (var image = SKImage.FromBitmap(resizedBitmap)) using (var compressedStream = new MemoryStream()) { // 以JPEG格式压缩,质量值0-100(值越小压缩率越高,70为清晰度与压缩率的平衡点) var encodedData = image.Encode(SKEncodedImageFormat.Jpeg, 70); encodedData.SaveTo(compressedStream); compressedStream.Position = 0; byte[] compressedBytes = compressedStream.ToArray(); string base64 = Convert.ToBase64String(compressedBytes); profil.Photo = base64; // 直接用压缩后的字节流显示图片,无需重复转Base64,提升性能 ImageProfil.Source = ImageSource.FromStream(() => new MemoryStream(compressedBytes)); Console.WriteLine($"压缩后Base64长度:{base64.Length}"); } } } } catch (Exception e) { await DisplayAlert("Erreur", e.Message, "ok"); } }
方案二:iOS原生API压缩(仅iOS平台)
如果你的应用仅面向iOS平台,可直接使用UIKit原生API压缩,性能更优。
操作步骤:
- 在iOS项目中添加压缩工具类:
using UIKit; using CoreGraphics; public static class ImageCompressor { public static byte[] CompressImage(byte[] originalData, int targetWidth = 200, int quality = 70) { using (var uiImage = UIImage.LoadFromData(NSData.FromArray(originalData))) { // 计算缩放比例 float scale = (float)targetWidth / uiImage.Size.Width; var newSize = new CGSize(targetWidth, uiImage.Size.Height * scale); // 绘制并压缩图片 UIGraphics.BeginImageContextWithOptions(newSize, false, 1.0f); uiImage.Draw(new CGRect(0, 0, newSize.Width, newSize.Height)); var compressedImage = UIGraphics.GetImageFromCurrentImageContext(); UIGraphics.EndImageContext(); // 转为JPEG字节数组 var compressedData = compressedImage.AsJPEG((nfloat)quality / 100); return compressedData.ToArray(); } } }
- 在共享项目中调用该方法:
async Task CapturePhoto() { try { var result = await MediaPicker.CapturePhotoAsync(); if (result != null) { using (var stream = await result.OpenReadAsync()) using (var memoryStream = new MemoryStream()) { stream.CopyTo(memoryStream); byte[] originalBytes = memoryStream.ToArray(); // 调用iOS原生压缩方法 byte[] compressedBytes = ImageCompressor.CompressImage(originalBytes); string base64 = Convert.ToBase64String(compressedBytes); profil.Photo = base64; ImageProfil.Source = ImageSource.FromStream(() => new MemoryStream(compressedBytes)); Console.WriteLine($"压缩后Base64长度:{base64.Length}"); } } } catch (Exception e) { await DisplayAlert("Erreur", e.Message, "ok"); } }
额外优化建议
- 拍照前可通过
MediaPickerOptions限制原始照片尺寸,进一步减少初始数据量:
var result = await MediaPicker.CapturePhotoAsync(new MediaPickerOptions { PhotoSize = PhotoSize.Medium // 可选Small/Medium/Large,或自定义尺寸 });
- 测试调整压缩质量值(60-80区间),找到适合你场景的清晰度与压缩率平衡点
内容的提问来源于stack exchange,提问作者Antoine21000
相关产品推荐
相关产品推荐

