博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Windows Azure: 使用Blob的PutBlock实现大文件断点续传
阅读量:5047 次
发布时间:2019-06-12

本文共 4191 字,大约阅读时间需要 13 分钟。

我们在使用Blob服务的时候,免不了要上传大文件,采用一般方式(UploadFromStream)上传数据,如果由于网络或是其他因素导致传输中断,则整个传输前功尽弃。针对这种情况,我们可以使用Blob的PutBlock机制将大文件分块(即分成若干个block)传输,并且实现断点续传。在这里我们通过一个例子来看看如何实现分块传输以及断点续传。

首先我们来看一下两个方法的定义:

PutBlock,上传单个Block数据。

1: public void PutBlock (
2:     string blockId,
3:     Stream blockData,
4:     string contentMD5
5: )
  • blockId, 使用Base64编码格式,代表了唯一的block;
  • blockData,block包含的数据流;
  • contentMD5,用来验证block完整性的哈希值,可以为Null或是空串。

PutBlockList:根据blockId集合提交所有的block,并创建或更新blob文件。只有提交以后,通过PutBlock上传的块数据才能成为Blob文件的一部分。

1: public void PutBlockList (
2:     IEnumerable
blockList,
3:     BlobRequestOptions options
4: )
  • blockList,blockId集合;
  • options,给请求定义的额外的配置。

对于分块传输的实现步骤,描述如下:

  1. 首先确定每一个block的大小,Blob服务规定Block最大不能超过4MB;
  2. 然后通过FileStream的Read方法依次按量读取块数据,并依次调用PutBlock将块数据上传,每次上传时需要一个对应的blockId,上传成功以后将对应的blockId存储;
  3. 所有Block上传完成以后,调用PutBlockList提交将才上传的所有block,组成blob文件。(注意,对于未提交的Block数据,一个星期之内将被自动回收。)

分块上传搞定以后,到底如何实现断点续传呢?

我们来看,假如100M的数据,每个block 1M,当我们上传了50个block的时候突然网断了,在网络断开的那一刻,我们能确定,到底成功上传了多少份Block,以及成功上传的block对应的block Id。对于同一文件,大小是不变的,所以我们可以根据传输了多少份block来确定续传时该从文件的那个位置开始继续读取block数据,并继续传输剩余的block。并且最后调用PutBlockList来提交网断前后上传的所有Block Id,最终完成传输。

好了,废话不多说,上代码,朋友们一看就明白。

这里使用了windows form application来演示断点续传,如图所示,点击"End”可模拟传输中断,再点击"Start”可模拟续传。

例子中使用了BackGroundWorker组件实现后台操作上传数据,前台进度条刷新。传输成功的block Id存储在内存中(List<string>),实际情况可能大家要考虑使用其他更为安全的存储方式以保证能续传。

断点续传分块数据主要代码:

 

1         private void UploadBigFile(BackgroundWorker worker, DoWorkEventArgs e) 2         { 3             //bufferSize 40KB 4             byte[] bufferBytes = new byte[bufferSize]; 5             string fileName = Path.GetFileName(filePath); 6              7             CloudBlockBlob blob = GetBlobkBlob(fileName); 8             using (FileStream fileStream = File.OpenRead(filePath)) 9             {10                 //Get the total count of block11                 blockCount = (int)(fileStream.Length / bufferSize) + 1;12                 Int64 currentBlockSize = 0;13                 for (int i = blockIds.Count; i < blockCount; i++)14                 {15                     if (worker.WorkerSupportsCancellation && worker.CancellationPending)16                     {17                         return;18                     }19                     currentBlockSize = bufferSize;20                     if (i == blockCount - 1)21                     {22                         currentBlockSize = fileStream.Length - bufferSize * i;23                         bufferBytes = new byte[currentBlockSize];24                     }25                     if (currentBlockSize == 0) break;26                     //Get the block data27                     fileStream.Read(bufferBytes, 0, Convert.ToInt32(currentBlockSize));28                     using (MemoryStream memoryStream = new MemoryStream(bufferBytes))29                     {30                         try31                         {32                             //Get Base64-encoded block Id33                             string blockId = Convert.ToBase64String(Encoding.UTF8.GetBytes(Guid.NewGuid().ToString()));34                             //Upload the block35                             blob.PutBlock(blockId, memoryStream, null);36                             //Cache the block Id37                             blockIds.Add(blockId);38                             worker.ReportProgress(i + 1);39                         }40                         catch (Exception)41                         {42 43                         }44                     }45                 }46             }47             //Commit all the blocks48             blob.PutBlockList(blockIds);49             isCanceled = false;50         }51 52         private CloudBlockBlob GetBlobkBlob(string fileName)53         {54             var storageAccount = CloudStorageAccount.Parse(storageConnectionString);55             CloudBlobClient blobStorage = storageAccount.CreateCloudBlobClient();56 57             CloudBlobContainer container = blobStorage.GetContainerReference("mycontainer");58             container.CreateIfNotExists();59 60             return container.GetBlockBlobReference(fileName);61         }

 

点击 下载源码。

转载于:https://www.cnblogs.com/lijiawei/archive/2013/01/18/2866756.html

你可能感兴趣的文章
php修改SESSION的有效生存时间
查看>>
spring security 11种过滤器介绍
查看>>
Hibernate一对多、多对一关联
查看>>
一、记录Git使用中遇到的问题及解决方法
查看>>
学习网址
查看>>
前端表格插件datatables
查看>>
内部类
查看>>
树链剖分入门
查看>>
图解算法时间复杂度
查看>>
UI_搭建MVC
查看>>
一个样例看清楚JQuery子元素选择器children()和find()的差别
查看>>
代码实现导航栏分割线
查看>>
Windows Phone开发(7):当好总舵主 转:http://blog.csdn.net/tcjiaan/article/details/7281421...
查看>>
VS 2010打开设计器出现错误
查看>>
SQLServer 镜像功能完全实现
查看>>
Vue-详解设置路由导航的两种方法
查看>>
一个mysql主从复制的配置案例
查看>>
大数据学习系列(8)-- WordCount+Block+Split+Shuffle+Map+Reduce技术详解
查看>>
dvwa网络渗透测试环境的搭建
查看>>
Win8 安装VS2012 和 Sql Server失败问题
查看>>