Как отобразить индикатор выполнения при загрузке данных в BLOB-объект Azure в приложении Магазина Windows
Я следовал за следующим постом, чтобы сделать загрузку кусками в блоб
Как отслеживать ход загрузки асинхронного файла в хранилище Azure
Но это не работает в приложении Windows Store или Windows 8.1, поскольку в приложении Win 8.1 отсутствует поддержка MemoryStream.
Во всяком случае, я изменил код в вышеупомянутой теме и придумал что-то вроде следующего
CloudBlobClient myBlobClient = storageAccount.CreateCloudBlobClient();
var filePicker = new FileOpenPicker();
filePicker.FileTypeFilter.Add("*");
var file = await filePicker.PickSingleFileAsync();
string output = string.Empty;
var fileName = file.Name;
myBlobClient.SingleBlobUploadThresholdInBytes = 1024 * 1024;
CloudBlobContainer container = myBlobClient.GetContainerReference("files");
//container.CreateIfNotExists();
CloudBlockBlob myBlob = container.GetBlockBlobReference(fileName);
var blockSize = 256 * 1024;
myBlob.StreamWriteSizeInBytes = blockSize;
var fileProp = await file.GetBasicPropertiesAsync();
var bytesToUpload = fileProp.Size;
var fileSize = bytesToUpload;
if (bytesToUpload < Convert.ToUInt64(blockSize))
{
CancellationToken ca = new CancellationToken();
var ado = myBlob.UploadFromFileAsync(file).AsTask();
await
//Console.WriteLine(ado.Status); //Does Not Help Much
ado.ContinueWith(t =>
{
//Console.WriteLine("Status = " + t.Status);
//Console.WriteLine("It is over"); //this is working OK
});
}
else
{
List<string> blockIds = new List<string>();
int index = 1;
ulong startPosition = 0;
ulong bytesUploaded = 0;
do
{
var bytesToRead = Math.Min(Convert.ToUInt64(blockSize), bytesToUpload);
var blobContents = new byte[bytesToRead];
using (Stream fs = await file.OpenStreamForWriteAsync())
{
fs.Position = Convert.ToInt64(startPosition);
fs.Read(blobContents, 0, (int)bytesToRead);
//var iStream = fs.AsInputStream();
ManualResetEvent mre = new ManualResetEvent(false);
var blockId = Convert.ToBase64String(Encoding.UTF8.GetBytes(index.ToString("d6")));
//Console.WriteLine("Now uploading block # " + index.ToString("d6"));
blockIds.Add(blockId);
var ado = myBlob.PutBlockAsync(blockId, fs.AsRandomAccessStream(), null).AsTask();
await ado.ContinueWith(t =>
{
bytesUploaded += bytesToRead;
bytesToUpload -= bytesToRead;
startPosition += bytesToRead;
index++;
double percentComplete = (double)bytesUploaded / (double)fileSize;
output += (percentComplete * 100).ToString() + ",";
// AppModel.TasksFormObj.SetProgress(percentComplete * 100);
// Console.WriteLine("Percent complete = " + percentComplete.ToString("P"));
mre.Set();
});
mre.WaitOne();
}
}
while (bytesToUpload > 0);
//Console.WriteLine("Now committing block list");
var pbl = myBlob.PutBlockListAsync(blockIds).AsTask();
pbl.ContinueWith(t =>
{
//Console.WriteLine("Blob uploaded completely.");
});
}
}
Приведенный выше код сохранит файл в BLOB-файле, и ход выполнения также будет нормальным, но сохраненный файл в BLOB-файле всегда будет иметь размер 0 байт. После отладки я обнаружил, что после var ado = myBlob.PutBlockAsync возникла ошибка (blockId, fs.AsRandomAccessStream(), null).AsTask(); для последней передачи BLOB-объекта как
<?xml version="1.0" encoding="utf-16"?>
<!--An exception has occurred. For more information please deserialize this message via RequestResult.TranslateFromExceptionMessage.-->
<RequestResult>
<HTTPStatusCode>400</HTTPStatusCode>
<HttpStatusMessage>The value for one of the HTTP headers is not in the correct format.</HttpStatusMessage>
<TargetLocation>Primary</TargetLocation>
<ServiceRequestID>13633308-0001-0031-060b-7249ea000000</ServiceRequestID>
<ContentMd5 />
<Etag />
<RequestDate>Sun, 28 Feb 2016 10:31:44 GMT</RequestDate>
<StartTime>Sun, 28 Feb 2016 09:31:43 GMT</StartTime>
<EndTime>Sun, 28 Feb 2016 09:31:44 GMT</EndTime>
<Error>
<Code>InvalidHeaderValue</Code>
<Message>The value for one of the HTTP headers is not in the correct format.
RequestId:13633308-0001-0031-060b-7249ea000000
Time:2016-02-28T09:34:18.3545085Z</Message>
<HeaderName>Content-Length</HeaderName>
<HeaderValue>0</HeaderValue>
</Error>
<ExceptionInfo>
<Type>StorageException</Type>
<HResult>-2147467259</HResult>
<Message>The value for one of the HTTP headers is not in the correct format.</Message>
<Source>Microsoft.WindowsAzure.Storage</Source>
<StackTrace> at Microsoft.WindowsAzure.Storage.Core.Executor.Executor.<ExecuteAsyncInternal>d__c`1.MoveNext()</StackTrace>
</ExceptionInfo>
</RequestResult>
Затем при последнем коммите выдается ошибка после myBlob.PutBlockListAsync(blockIds), поскольку указанный список блоков недействителен
Поэтому, пожалуйста, кто-нибудь, помогите мне выяснить, где я делаю что-то не так или как можно решить эту проблему на 100%.
1 ответ
Использование AsTask()
как это.
CancellationTokenSource _cts;
_cts = new CancellationTokenSource();//<--In Constructor
var progress = new Progress<double>(TranscodeProgress);
await var ado = myBlob.UploadFromFileAsync(file).AsTask(_cts.Token, progress);