UWP拖拽场景:无需流或通过流保存StorageItem/XAML Image图片的方法
解决方法:从Drop事件的StorageItem保存图片并获取路径
其实你已经拿到了最关键的StorageFile对象,完全可以直接基于它来操作,不用绕到BitmapImage或者Image控件,这样更高效也更简单。下面给你两种常用的方案:
方案一:直接复制原始文件到目标位置(最简单)
如果不需要转换图片格式,直接把拖拽进来的文件复制到你指定的文件夹(比如应用的本地文件夹、或者用户选择的文件夹),就能直接拿到文件路径,完美满足上传需求。
修改你的代码如下:
private async void Galerie_Drop(object sender, DragEventArgs e) { if (e.DataView.Contains(StandardDataFormats.StorageItems)) { var items = await e.DataView.GetStorageItemsAsync(); // 先确定保存的目标文件夹,比如应用的本地文件夹 var targetFolder = ApplicationData.Current.LocalFolder; // 或者让用户选择文件夹:var targetFolder = await new FolderPicker().PickSingleFolderAsync(); foreach (StorageFile storageItem in items) { // 复制文件到目标文件夹,避免重名可以加个随机后缀 var newFileName = $"{Guid.NewGuid()}_{storageItem.Name}"; var savedFile = await storageItem.CopyAsync(targetFolder, newFileName, NameCollisionOption.ReplaceExisting); // 这里的savedFile.Path就是你要的文件路径,直接用来上传就行 string uploadPath = savedFile.Path; // 同时继续显示图片的逻辑 BitmapImage droppedImages = new BitmapImage(); droppedImages.SetSource(await storageItem.OpenReadAsync()); // ... 把droppedImages绑定到Image控件的代码 } } }
方案二:转换图片格式后保存(如需转PNG/JPG)
如果需要把图片统一转成指定格式(比如全部转成PNG),那就要用到Stream和图片编解码API了。可以从StorageFile打开流,解码后再编码成目标格式保存:
private async void Galerie_Drop(object sender, DragEventArgs e) { if (e.DataView.Contains(StandardDataFormats.StorageItems)) { var items = await e.DataView.GetStorageItemsAsync(); var targetFolder = ApplicationData.Current.LocalFolder; foreach (StorageFile storageItem in items) { // 1. 打开原始文件的流并解码 using (var originalStream = await storageItem.OpenAsync(FileAccessMode.Read)) { var decoder = await BitmapDecoder.CreateAsync(originalStream); var pixelData = await decoder.GetPixelDataAsync(); // 2. 创建目标文件并编码成指定格式(这里以PNG为例) var targetFile = await targetFolder.CreateFileAsync($"{Guid.NewGuid()}.png", CreationCollisionOption.ReplaceExisting); using (var targetStream = await targetFile.OpenAsync(FileAccessMode.ReadWrite)) { var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, targetStream); encoder.SetPixelData( decoder.BitmapPixelFormat, decoder.BitmapAlphaMode, decoder.PixelWidth, decoder.PixelHeight, decoder.DpiX, decoder.DpiY, pixelData.DetachPixelData()); await encoder.FlushAsync(); } // 拿到转换后的文件路径 string uploadPath = targetFile.Path; } // 显示图片的逻辑不变 BitmapImage droppedImages = new BitmapImage(); droppedImages.SetSource(await storageItem.OpenReadAsync()); // ... 绑定到Image控件 } } }
额外说明:要不要从BitmapImage/Image控件入手?
其实不建议这么做,因为BitmapImage是专为显示优化的,它的内部流可能已经被处理或释放,获取起来需要额外用WriteableBitmap中转,步骤更繁琐。直接用原始的StorageFile是最直接高效的方式——毕竟你本来就从Drop事件里拿到了它。
内容的提问来源于stack exchange,提问作者JL_Funk
相关产品推荐
相关产品推荐

