Uwp 如何在异步更新进度时成功地将blob流复制到文件或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),它工作得很好 如果我使用该方法,结果是一个文件存储在

我一直在尝试在下载或上传时提前更新我的下载百分比,上传一点问题都没有,它工作得很好。 但是,当我尝试下载一个文件并在等待其结束时尝试更新进度百分比时,一旦我结束下载,我就会将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);
它将我的流完全复制到我之前设置的位置