VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > 编程开发 > c#编程 >
  • C#中关于Azure Storage——文件上传与下载

第五部分:云原生与无服务器开发
2. Azure Storage——文件上传与下载
实例介绍
之前做电商后台的商品图片上传功能时,用本地文件系统存储,需要维护服务器存储,扩容麻烦,而且无法实现多服务器共享。换成Azure Storage后,图片存储在Blob存储中,支持无限扩容,多服务器可直接访问,还能通过CDN加速vb.net教程C#教程python教程SQL教程access 2010教程访问,图片加载速度提升50%,维护成本降为0。这节就带你从零实现Azure Storage的文件上传与下载,包括Blob存储、文件存储、队列存储、表存储,覆盖云存储的核心场景。
需求分析
Azure Storage要解决“无限扩容、高可用性、多服务器共享、CDN加速、安全存储、成本优化”的问题,具体需求如下:
1.Blob存储:存储非结构化数据(如图片、视频、文档、备份文件);
2.文件存储:存储结构化数据(如共享文件、日志文件),支持SMB协议;
3.队列存储:存储消息,实现异步任务处理(如订单通知、数据同步);
4.表存储:存储结构化数据(如用户信息、设备数据),支持NoSQL查询;
5.高可用性:数据自动复制到多个区域,99.999999999%的持久性;
6.安全存储:支持加密(静态加密、传输加密)、访问控制(SAS令牌、RBAC);
7.CDN加速:通过Azure CDN加速Blob存储的访问,降低延迟;
8.成本优化:支持分层存储(热存储、冷存储、归档存储),根据访问频率选择存储层;
9.本地开发:支持本地开发、调试,使用Azurite模拟器模拟Azure Storage;
10.监控与日志:集成Azure Monitor,实时监控存储使用情况、查看访问日志;
代码实现
前置条件:.NET 8 SDK;Azure账户(免费试用即可);需安装以下NuGet包:
Azure.Storage.Blobs:Blob存储客户端库
Azure.Storage.Files.Shares:文件存储客户端库
Azure.Storage.Queues:队列存储客户端库
Azure.Data.Tables:表存储客户端库
Azurite:本地Azure Storage模拟器(可选,用于本地开发)
场景1:Blob存储——图片上传与下载
实现Blob存储的文件上传、下载、删除、列出文件,支持分层存储、SAS令牌访问。
步骤1:创建Azure存储账户
1.登录Azure门户(https://portal.azure.com);
2.点击“创建资源” → 搜索“存储账户” → 点击“创建”;
3.配置存储账户:
订阅:选择你的Azure订阅;
资源组:使用之前创建的资源组(如AzureFunctionsDemoRG);
存储账户名称:全局唯一名称(如azurestoragedemo2026);
位置:选择靠近你的区域(如“东亚”);
性能:选择“标准”(适合大多数场景);
冗余:选择“本地冗余存储(LRS)”(成本低,数据复制到同一区域的3个副本);
4.点击“查看+创建” → “创建”,等待存储账户创建完成;
5.创建Blob容器:在存储账户中点击“容器” → “创建”,输入容器名称(如product-images),公共访问级别选择“私有(无匿名访问)”;
步骤2:获取存储账户连接字符串
1.在Azure门户中打开存储账户 → 点击“访问密钥” → 复制“连接字符串”;
2.将连接字符串保存到配置文件(如appsettings.json);
步骤3:Blob存储操作代码
csharp

	using Azure.Storage.Blobs;
	using Azure.Storage.Blobs.Models;
	using Azure.Storage.Sas;
	
	namespace AzureStorageDemo.Services;
	
	public class BlobStorageService
	{
	private readonly BlobServiceClient _blobServiceClient;
	private readonly string _containerName = "product-images";
	
	public BlobStorageService(string connectionString)
	{
	// 初始化Blob服务客户端
	_blobServiceClient = new BlobServiceClient(connectionString);
	}
	
	// 上传文件到Blob存储
	public async Task UploadFileAsync(string localFilePath, string blobName, string storageTier = "Hot")
	{
	// 获取容器客户端
	var blobContainerClient = _blobServiceClient.GetBlobContainerClient(_containerName);
	// 确保容器存在
	await blobContainerClient.CreateIfNotExistsAsync();
	
	// 获取Blob客户端
	var blobClient = blobContainerClient.GetBlobClient(blobName);
	
	// 上传文件
	using var fileStream = File.OpenRead(localFilePath);
	await blobClient.UploadAsync(fileStream, new BlobUploadOptions
	{
	// 设置存储层:Hot(热存储,频繁访问)、Cool(冷存储,不频繁访问)、Archive(归档存储,极少访问)
	AccessTier = storageTier switch
	{
	"Cool" => AccessTier.Cool,
	"Archive" => AccessTier.Archive,
	_ => AccessTier.Hot
	}
	});
	
	Console.WriteLine($"文件 {blobName} 上传成功!");
	}
	
	// 从Blob存储下载文件
	public async Task DownloadFileAsync(string blobName, string localFilePath)
	{
	var blobContainerClient = _blobServiceClient.GetBlobContainerClient(_containerName);
	var blobClient = blobContainerClient.GetBlobClient(blobName);
	
	// 下载文件
	using var fileStream = File.OpenWrite(localFilePath);
	await blobClient.DownloadToAsync(fileStream);
	
	Console.WriteLine($"文件 {blobName} 下载成功!");
	}
	
	// 删除Blob存储中的文件
	public async Task DeleteFileAsync(string blobName)
	{
	var blobContainerClient = _blobServiceClient.GetBlobContainerClient(_containerName);
	var blobClient = blobContainerClient.GetBlobClient(blobName);
	
	await blobClient.DeleteIfExistsAsync();
	
	Console.WriteLine($"文件 {blobName} 删除成功!");
	}
	
	// 列出Blob存储中的所有文件
	public async Task<List<string>> ListFilesAsync()
	{
	var blobContainerClient = _blobServiceClient.GetBlobContainerClient(_containerName);
	var files = new List<string>();
	
	await foreach (var blobItem in blobContainerClient.GetBlobsAsync())
	{
	files.Add(blobItem.Name);
	Console.WriteLine($"文件:{blobItem.Name},大小:{blobItem.Properties.ContentLength}字节,存储层:{blobItem.Properties.AccessTier}");
	}
	
	return files;
	}
	
	// 生成SAS令牌,用于临时访问Blob
	public string GenerateSasToken(string blobName, TimeSpan expiresIn)
	{
	var blobContainerClient = _blobServiceClient.GetBlobContainerClient(_containerName);
	var blobClient = blobContainerClient.GetBlobClient(blobName);
	
	// 生成SAS令牌
	var sasBuilder = new BlobSasBuilder()
	{
	BlobContainerName = _containerName,
	BlobName = blobName,
	Resource = "b", // "b"表示Blob,"c"表示容器
	ExpiresOn = DateTimeOffset.UtcNow.Add(expiresIn)
	};
	
	// 设置权限:读取、写入、删除等
	sasBuilder.SetPermissions(BlobSasPermissions.Read);
	
	// 生成SAS URI
	var sasUri = blobClient.GenerateSasUri(sasBuilder);
	return sasUri.Query; // 返回SAS令牌部分(?sv=...&ss=...&srt=...)
	}
	}

场景2:文件存储——共享文件上传与下载
实现文件存储的共享文件上传、下载、删除、列出文件,支持SMB协议,可在Windows、Linux、macOS上访问。
步骤1:创建文件共享
1.在Azure门户中打开存储账户 → 点击“文件共享” → “创建”,输入共享名称(如shared-files);
步骤2:文件存储操作代码
csharp

	using Azure.Storage.Files.Shares;
	using Azure.Storage.Files.Shares.Models;
	
	namespace AzureStorageDemo.Services;
	
	public class FileStorageService
	{
	private readonly ShareServiceClient _shareServiceClient;
	private readonly string _shareName = "shared-files";
	
	public FileStorageService(string connectionString)
	{
	_shareServiceClient = new ShareServiceClient(connectionString);
	}
	
	// 上传文件到文件存储
	public async Task UploadFileAsync(string localFilePath, string fileName)
	{
	var shareClient = _shareServiceClient.GetShareClient(_shareName);
	await shareClient.CreateIfNotExistsAsync();
	
	// 获取目录客户端(根目录)
	var directoryClient = shareClient.GetRootDirectoryClient();
	// 获取文件客户端
	var fileClient = directoryClient.GetFileClient(fileName);
	
	// 上传文件
	using var fileStream = File.OpenRead(localFilePath);
	await fileClient.CreateAsync(fileStream.Length);
	await fileClient.UploadRangeAsync(new HttpRange(0, fileStream.Length), fileStream);
	
	Console.WriteLine($"文件 {fileName} 上传成功!");
	}
	
	// 从文件存储下载文件
	public async Task DownloadFileAsync(string fileName, string localFilePath)
	{
	var shareClient = _shareServiceClient.GetShareClient(_shareName);
	var directoryClient = shareClient.GetRootDirectoryClient();
	var fileClient = directoryClient.GetFileClient(fileName);
	
	// 下载文件
	using var fileStream = File.OpenWrite(localFilePath);
	var response = await fileClient.DownloadAsync();
	await response.Value.Content.CopyToAsync(fileStream);
	
	Console.WriteLine($"文件 {fileName} 下载成功!");
	}
	
	// 列出文件存储中的所有文件
	public async Task<List<string>> ListFilesAsync()
	{
	var shareClient = _shareServiceClient.GetShareClient(_shareName);
	var directoryClient = shareClient.GetRootDirectoryClient();
	var files = new List<string>();
	
	await foreach (var fileItem in directoryClient.GetFilesAndDirectoriesAsync())
	{
	if (fileItem.IsDirectory)
	{
	Console.WriteLine($"目录:{fileItem.Name}");
	}
	else
	{
	files.Add(fileItem.Name);
	Console.WriteLine($"文件:{fileItem.Name}");
	}
	}
	
	return files;
	}
	}

场景3:队列存储——异步任务处理
实现队列存储的消息发送、接收、删除,支持异步任务处理(如订单通知、数据同步)。
步骤1:创建队列
1.在Azure门户中打开存储账户 → 点击“队列” → “创建”,输入队列名称(如order-notifications);
步骤2:队列存储操作代码
csharp

	using Azure.Storage.Queues;
	using Azure.Storage.Queues.Models;
	
	namespace AzureStorageDemo.Services;
	
	public class QueueStorageService
	{
	private readonly QueueServiceClient _queueServiceClient;
	private readonly string _queueName = "order-notifications";
	
	public QueueStorageService(string connectionString)
	{
	_queueServiceClient = new QueueServiceClient(connectionString);
	}
	
	// 发送消息到队列
	public async Task SendMessageAsync(string messageContent, TimeSpan? visibilityTimeout = null)
	{
	var queueClient = _queueServiceClient.GetQueueClient(_queueName);
	await queueClient.CreateIfNotExistsAsync();
	
	// 发送消息,visibilityTimeout表示消息的可见性延迟(如设置为5分钟,5分钟后才能被接收)
	await queueClient.SendMessageAsync(messageContent, visibilityTimeout: visibilityTimeout);
	
	Console.WriteLine($"消息发送成功:{messageContent}");
	}
	
	// 接收队列中的消息
	public async Task<string?> ReceiveMessageAsync(TimeSpan visibilityTimeout = default)
	{
	var queueClient = _queueServiceClient.GetQueueClient(_queueName);
	if (!await queueClient.ExistsAsync())
	{
	Console.WriteLine("队列不存在!");
	return null;
	}
	
	// 接收消息,visibilityTimeout表示消息的锁定时间(如设置为30秒,30秒内其他客户端无法接收该消息)
	var response = await queueClient.ReceiveMessageAsync(visibilityTimeout: visibilityTimeout);
	if (response.Value != null)
	{
	Console.WriteLine($"接收到消息:{response.Value.MessageText}");
	return response.Value.MessageId;
	}
	else
	{
	Console.WriteLine("队列中没有消息!");
	return null;
	}
	}
	
	// 删除队列中的消息
	public async Task DeleteMessageAsync(string messageId, string popReceipt)
	{
	var queueClient = _queueServiceClient.GetQueueClient(_queueName);
	await queueClient.DeleteMessageAsync(messageId, popReceipt);
	
	Console.WriteLine($"消息 {messageId} 删除成功!");
	}
	}

场景4:表存储——NoSQL数据存储
实现表存储的实体插入、查询、更新、删除,支持NoSQL查询,适合存储结构化数据(如用户信息、设备数据)。
步骤1:创建表
1.在Azure门户中打开存储账户 → 点击“表” → “创建”,输入表名称(如users);
步骤2:表存储操作代码
csharp

	using Azure.Data.Tables;
	
	namespace AzureStorageDemo.Services;
	
	// 用户实体类,必须实现ITableEntity接口
	public class UserEntity : ITableEntity
	{
	// 分区键(用于水平分区,提高查询性能)
	public string PartitionKey { get; set; } = string.Empty;
	// 行键(唯一标识分区内的实体)
	public string RowKey { get; set; } = string.Empty;
	// 时间戳(自动生成,用于并发控制)
	public DateTimeOffset? Timestamp { get; set; }
	// ETag(自动生成,用于并发控制)
	public ETag ETag { get; set; }
	
	// 自定义属性
	public string UserName { get; set; } = string.Empty;
	public string Email { get; set; } = string.Empty;
	public int Age { get; set; }
	public bool IsActive { get; set; }
	}
	
	public class TableStorageService
	{
	private readonly TableServiceClient _tableServiceClient;
	private readonly string _tableName = "users";
	
	public TableStorageService(string connectionString)
	{
	_tableServiceClient = new TableServiceClient(connectionString);
	}
	
	// 插入用户实体
	public async Task InsertUserAsync(UserEntity user)
	{
	var tableClient = _tableServiceClient.GetTableClient(_tableName);
	await tableClient.CreateIfNotExistsAsync();
	
	await tableClient.AddEntityAsync(user);
	
	Console.WriteLine($"用户 {user.UserName} 插入成功!");
	}
	
	// 查询用户实体(按分区键和行键查询)
	public async Task<UserEntity?> GetUserAsync(string partitionKey, string rowKey)
	{
	var tableClient = _tableServiceClient.GetTableClient(_tableName);
	try
	{
	var user = await tableClient.GetEntityAsync<UserEntity>(partitionKey, rowKey);
	return user.Value;
	}
	catch (Azure.RequestFailedException ex) when (ex.Status == 404)
	{
	Console.WriteLine("用户不存在!");
	return null;
	}
	}
	
	// 查询所有用户实体
	public async Task<List<UserEntity>> GetAllUsersAsync()
	{
	var tableClient = _tableServiceClient.GetTableClient(_tableName);
	var users = new List<UserEntity>();
	
	await foreach (var user in tableClient.QueryAsync<UserEntity>())
	{
	users.Add(user);
	Console.WriteLine($"用户:{user.UserName},邮箱:{user.Email},年龄:{user.Age}");
	}
	
	return users;
	}
	
	// 更新用户实体
	public async Task UpdateUserAsync(UserEntity user)
	{
	var tableClient = _tableServiceClient.GetTableClient(_tableName);
	await tableClient.UpdateEntityAsync(user, ETag.All, TableUpdateMode.Replace);
	
	Console.WriteLine($"用户 {user.UserName} 更新成功!");
	}
	}

场景5:本地开发与调试
使用Azurite模拟器模拟Azure Storage,实现本地开发、调试,无需连接Azure云。
步骤1:安装Azurite
bash
dotnet tool install -g Azurite
步骤2:启动Azurite
bash
azurite
Azurite默认监听端口:Blob存储10000,队列存储10001,表存储10002;
步骤3:使用Azurite连接字符串
csharp

	// Azurite连接字符串
	string connectionString = "DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1;QueueEndpoint=http://127.0.0.1:10001/devstoreaccount1;TableEndpoint=http://127.0.0.1:10002/devstoreaccount1;";
	
	var blobStorageService = new BlobStorageService(connectionString);

逐行讲解
场景1:Blob存储核心代码
1.BlobServiceClient:
用于管理Blob存储账户,创建容器客户端、获取容器列表等;
2.BlobContainerClient:
用于管理Blob容器,创建容器、获取Blob客户端、列出Blob等;
3.BlobClient:
用于管理单个Blob,上传、下载、删除Blob,生成SAS令牌等;
4.存储层:
热存储(Hot):适合频繁访问的数据,存储成本高,访问成本低;
冷存储(Cool):适合不频繁访问的数据(每月访问少于1次),存储成本低,访问成本高;
归档存储(Archive):适合极少访问的数据(每年访问少于1次),存储成本极低,访问成本极高,需要解冻才能访问;
场景3:队列存储核心代码
1.QueueServiceClient:
用于管理队列存储账户,创建队列客户端、获取队列列表等;
2.QueueClient:
用于管理单个队列,发送、接收、删除消息,创建、删除队列等;
3.消息可见性:
visibilityTimeout:发送消息时设置,消息在指定时间后才能被接收;
visibilityTimeout:接收消息时设置,消息在指定时间内被锁定,其他客户端无法接收;
场景4:表存储核心代码
1.ITableEntity接口:
实体类必须实现该接口,包含PartitionKey、RowKey、Timestamp、ETag属性;
2.分区键(PartitionKey):
用于水平分区,将数据分布到多个服务器,提高查询性能;
建议将经常一起查询的实体放在同一个分区;
3.行键(RowKey):
唯一标识分区内的实体,与PartitionKey一起构成实体的唯一标识;
基础知识拓展

  1. Azure Storage类型对比
存储类型 特点 适用场景
Blob存储 存储非结构化数据,支持分层存储、CDN加速 图片、视频、文档、备份文件、静态网站
文件存储 存储结构化数据,支持SMB协议,可在多平台访问 共享文件、日志文件、应用程序配置文件
队列存储 存储消息,实现异步任务处理,支持消息可见性、锁定 订单通知、数据同步、异步任务处理
表存储 存储结构化数据,支持NoSQL查询,水平扩展 用户信息、设备数据、日志数据、元数据
  1. 安全存储最佳实践
    1.加密:
    静态加密:Azure自动加密存储的数据,使用Azure管理的密钥或客户管理的密钥;
    传输加密:使用HTTPS协议传输数据,禁止HTTP访问;
    2.访问控制:
    SAS令牌:生成临时访问令牌,授予特定权限(如读取、写入),设置过期时间;
    RBAC角色:为用户、组、服务主体分配存储账户角色(如Storage Blob Data Contributor);
    3.防火墙:配置存储账户防火墙,只允许特定IP地址或虚拟网络访问;
  2. 成本优化策略
    1.分层存储:根据数据访问频率选择存储层,将不频繁访问的数据移到冷存储或归档存储;
    2.生命周期管理:配置生命周期规则,自动将数据从热存储移到冷存储、归档存储,或删除过期数据;
    3.冗余策略:选择合适的冗余策略(LRS、GRS、RA-GRS、ZRS、GZRS、RA-GZRS),平衡成本和可用性;
  3. 监控与日志
    Azure Monitor:实时监控存储使用情况(如存储容量、请求次数、响应时间);
    存储分析日志:记录存储账户的访问日志,可用于审计、故障排查;
    指标警报:设置指标警报(如存储容量超过阈值、请求错误率过高),及时通知管理员;
    总结
    Azure Storage的核心是无限扩容、高可用性、多场景支持、安全存储、成本优化,让你轻松存储和管理各种类型的数据,无需担心服务器扩容、维护、故障恢复。关键要点:
    1.Blob存储:存储非结构化数据,支持分层存储、CDN加速;
    2.文件存储:存储结构化数据,支持SMB协议,多平台访问;
    3.队列存储:存储消息,实现异步任务处理,提高系统响应速度;
    4.表存储:存储结构化数据,支持NoSQL查询,水平扩展;
    5.安全存储:支持加密、访问控制、防火墙,保护数据安全;
    6.成本优化:分层存储、生命周期管理,降低存储成本;
    比如这个Azure Storage商品图片存储功能,图片存储在热存储层,通过CDN加速访问,加载速度提升50%,每月存储成本不到50元,而且不需要维护服务器,维护成本降为0。掌握Azure Storage,你就能轻松构建云原生应用,实现数据的安全存储、高效访问!

本站原创,转载请注明出处:


相关教程