Uwp 如何在异步更新进度时成功地将blob流复制到文件或filestream。?
我一直在尝试在下载或上传时提前更新我的下载百分比,上传一点问题都没有,它工作得很好。 但是,当我尝试下载一个文件并在等待其结束时尝试更新进度百分比时,一旦我结束下载,我就会将mediaStream复制到一个文件流,结果总是得到一个空文件:0Kb 一开始,我认为我的服务器端代码有问题,它是生成SasToken、filename和Uri的代码 但是如果我使用blobStorage.DownloadToStreamAsync(fileStream),它工作得很好 如果我使用该方法,结果是一个文件存储在我想要的地方,具有适当的扩展名 这是我的测试代码:Uwp 如何在异步更新进度时成功地将blob流复制到文件或filestream。?,uwp,azure-mobile-services,azure-storage-blobs,template10,storagefile,Uwp,Azure Mobile Services,Azure Storage Blobs,Template10,Storagefile,我一直在尝试在下载或上传时提前更新我的下载百分比,上传一点问题都没有,它工作得很好。 但是,当我尝试下载一个文件并在等待其结束时尝试更新进度百分比时,一旦我结束下载,我就会将mediaStream复制到一个文件流,结果总是得到一个空文件:0Kb 一开始,我认为我的服务器端代码有问题,它是生成SasToken、filename和Uri的代码 但是如果我使用blobStorage.DownloadToStreamAsync(fileStream),它工作得很好 如果我使用该方法,结果是一个文件存储在
private async Task ExecuteDownloadFileCommand()
{
var busyView = new Busy();
busyView.IsBusy = true;
Busy.SetBusy(busyView.IsBusy, $"Please Wait...\nDownloading: {FileProgress * 100}");
try
{
// Get the SAS token from the backend
ICloudService cloudService = ServiceLocator.Instance.Resolve<ICloudService>();
var storageToken = await cloudService.GetSasTokenAsync("7ec0d415c1994082a954ae6329b02915");
// Use the SAS token to get a reference to the blob storage
var storageUri = new Uri($"{storageToken.Uri}{storageToken.SasToken}");
var blobStorage = new CloudBlockBlob(storageUri);
//Organize the store file process.
var storageFolder = await StorageFolder.GetFolderFromPathAsync(ApplicationData.Current.TemporaryFolder.Path);
var savePicker = new Windows.Storage.Pickers.FileSavePicker();
savePicker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.PicturesLibrary;
savePicker.FileTypeChoices.Add("Picture", new List<string> { ".jpg" });
savePicker.SuggestedFileName = "photo.jpg";
var storageDestinationFile = await savePicker.PickSaveFileAsync();
FileStream fileStream = null;
await Task.Run(() =>
{
fileStream = File.Create(storageDestinationFile.Path);
});
//await blobStorage.DownloadToStreamAsync(fileStream); //this line of code gives me the result i want.
using (var mediaStream = await blobStorage.OpenReadAsync())
{
var bytesInBlocks = 1024;
var mediaLength = mediaStream.Length;
byte[] buffer = new byte[bytesInBlocks];
var bytesRead = 0;
double totalBytesRead = 0.0;
var blocksRead = 0;
var blockIds = new List<string>();
IsDownloadingFile = true;
FileProgress = 0.0;
// Do what you need to for opening your output file
do
{
bytesRead = await mediaStream.ReadAsync(buffer, 0, bytesInBlocks);
if (bytesRead > 0)
{
//Update the interval counters
totalBytesRead += bytesRead;
blocksRead++;
//Update the progress bar.
var progress = totalBytesRead / mediaLength;
FileProgress = progress;
Busy.SetBusy(busyView.IsBusy, $"Please Wait... \nDownloading: {FileProgress * 100}");
}
} while (bytesRead > 0);
mediaStream.CopyTo(fileStream); //this line of code isnt copying anything.
//using (var mediaRandomAccessStream = mediaStream.AsRandomAccessStream())
//{
// using (var mediaInputStream = mediaRandomAccessStream.GetInputStreamAt(0)) //this line of code throws and exception because the randomaccess code cant be clone.
// {
// using (var destinationStream = await storageDestinationFile.OpenAsync(FileAccessMode.ReadWrite))
// {
// using (var destinationOutputStream = destinationStream.GetOutputStreamAt(0))
// {
// await RandomAccessStream.CopyAndCloseAsync(mediaRandomAccessStream, destinationOutputStream);
// }
// }
// }
//}
}
fileStream.Dispose();
}
catch (Exception ex)
{
Debug.WriteLine($"[TaskListViewModel] Downloading error: {ex.Message}");
}
finally
{
busyView.IsBusy = false;
IsDownloadingFile = false;
FileProgress = 0.0;
Busy.SetBusy(busyView.IsBusy);
}
}
private async Task ExecuteDownloadFileCommand()
{
var busyView=new Busy();
busyView.IsBusy=true;
Busy.SetBusy(busyView.IsBusy,$“请稍候…\n下载:{FileProgress*100}”);
尝试
{
//从后端获取SAS令牌
ICloudService cloudService=ServiceLocator.Instance.Resolve();
var storageToken=await cloudService.GetSasTokenAsync(“7ec0d415c1994082a954ae6329b02915”);
//使用SAS令牌获取对blob存储的引用
var storageUri=新Uri($“{storageToken.Uri}{storageToken.SasToken}”);
var blobStorage=新的CloudBlockBlob(storageUri);
//组织存储文件过程。
var storageFolder=wait-storageFolder.GetFolderFromPathAsync(ApplicationData.Current.TemporaryFolder.Path);
var savePicker=new Windows.Storage.Pickers.FileSavePicker();
savePicker.SuggestedStartLocation=Windows.Storage.Pickers.PickerLocationId.PicturesLibrary;
savePicker.FileTypeChoices.Add(“图片”,新列表{.jpg});
savePicker.SuggestedFileName=“photo.jpg”;
var storageDestinationFile=wait savePicker.PickSaveFileAsync();
FileStream FileStream=null;
等待任务。运行(()=>
{
fileStream=File.Create(storageDestinationFile.Path);
});
//wait blobStorage.DownloadToStreamAsync(fileStream);//这行代码给出了我想要的结果。
使用(var mediaStream=await blobStorage.OpenReadAsync())
{
var bytesinblock=1024;
var medialLength=mediaStream.Length;
byte[]buffer=新字节[bytesinblock];
var bytesRead=0;
双totalBytesRead=0.0;
var blocksRead=0;
var blockIds=新列表();
IsDownloadingFile=true;
FileProgress=0.0;
//执行打开输出文件所需的操作
做
{
bytesRead=wait mediaStream.ReadAsync(缓冲区,0,bytesinblock);
如果(字节读取>0)
{
//更新间隔计数器
totalBytesRead+=字节读取;
blocksRead++;
//更新进度条。
var progress=totalBytesRead/mediaLength;
FileProgress=进度;
Busy.SetBusy(busyView.IsBusy,$“请稍候…\n下载:{FileProgress*100}”);
}
}而(字节读取>0);
mediaStream.CopyTo(fileStream);//这行代码没有复制任何内容。
//使用(var mediaRandomAccessStream=mediaStream.AsRandomAccessStream())
//{
//使用(var mediaInputStream=mediaRandomAccessStream.GetInputStreamAt(0))//这行代码引发异常,因为无法克隆randomaccess代码。
// {
//使用(var destinationStream=await-storageDestinationFile.OpenAsync(FileAccessMode.ReadWrite))
// {
//使用(var destinationOutputStream=destinationStream.GetOutputStreamAt(0))
// {
//等待RandomAccessStream.CopyAndCloseAsync(mediaRandomAccessStream,destinationOutputStream);
// }
// }
// }
//}
}
Dispose();
}
捕获(例外情况除外)
{
Debug.WriteLine($“[TaskListViewModel]下载错误:{ex.Message}”);
}
最后
{
busyView.IsBusy=false;
IsDownloadingFile=false;
FileProgress=0.0;
Busy.SetBusy(busyView.IsBusy);
}
}
现在我在使用UWP,我也在使用模板10,它促进了我在UWP中的开发,我想要的是能够完全下载一个文件,同时向我的最终用户显示下载进度
但我似乎还没能做到这一点
希望有人能给我指出正确的方向。事实证明,我所需要做的就是像这样移动到流的开头:
mediaStream.Seek(0, SeekOrigin.Begin);
await mediaStream.CopyToAsync(fileStream);
它将我的流完全复制到我之前设置的位置