C# Azure File Share文件上传 C#如何像操作本地磁盘一样读写Azure文件共享

1次阅读

cloudfileclient 通过 rest api 操作 azure 文件共享,需用 cloudfileshare 等四层对象而非本地路径;须正确初始化凭据、设置流位置为0、预估内存容量、避免路径编码与 smb 混用。

C# Azure File Share文件上传 C#如何像操作本地磁盘一样读写Azure文件共享

CloudFileClient 连上 Azure 文件共享,不是挂载成盘符

Azure 文件共享(Azure File Share)本质是 SMB 协议服务,但 C# SDK 不提供“映射为本地驱动器”这种 OS 层操作——它走的是 REST API 路径。所以你不能像 File.WriteAllText(@"Z: est.txt", "hi") 那样直接用路径写,必须通过 CloudFileClient + CloudFileShare + CloudFileDirectory + CloudFile 四层对象来操作。

常见错误现象:UnauthorizedAccessExceptionFileNotFoundException,往往是因为跳过了认证初始化,或误把共享名当成了目录路径传给 GetRootDirectoryReference()

  • 连接前必须用 StorageCredentials(推荐用 StorageSharedKeyCredential,非 SAS Token)构造 CloudFileClient
  • 共享名(share name)是 URL 中的第三段,比如 https://mystorage.file.core.windows.net/mysharemyshare 才是 GetShareReference("myshare") 的参数
  • 根目录固定用 GetRootDirectoryReference() 获取,不要拼接 """/"

UploadFromStreamAsync 上传文件:注意流位置和缓冲区大小

上传不是“复制字节”,而是把流内容推到 Azure 文件服务。如果传入的 Stream 已经读到末尾(position == Length),上传会成功但内容为空——这是最常被忽略的坑。

使用场景:上传内存流、文件流、HTTP 响应流等。不建议直接传 FileStream 且未设置 FileAccess.Read;也不建议用 MemoryStream 装 GB 级数据再上传,容易 OOM。

  • 上传前务必检查 stream.Position = 0,尤其对 MemoryStream
  • 大文件(>100MB)建议分块上传,用 UploadFromStreamAsync(stream, NULL, null, new FileRequestOptions { ParallelOperationThreadCount = 4 })
  • 默认单次上传上限是 256MB;超限会抛 StorageException,错误信息含 "The specified blob or block content is invalid."

下载文件时别直接 DownloadToStreamAsync 到未扩容的 MemoryStream

下载接口不会自动扩容目标 MemoryStream,如果它初始容量不足,会触发 ArgumentException: Stream was too long。这不是网络问题,是本地流容量没预估好。

使用场景:读取配置文件、小图片、日志片段等需要即时解析的内容。若只是保存到磁盘,优先用 DownloadToFileAsync

  • 安全做法:先调用 file.Properties.Length 获取大小,再创建对应容量的 MemoryStream,例如 new MemoryStream((int)file.Properties.Length)
  • 若长度未知(如某些元数据未刷新),改用 DownloadToStreamAsync(new MemoryStream()) 是可行的,但要注意 GC 压力
  • 下载大文件时,DownloadToStreamAsync 默认启用 4MB 缓冲区;如需控制内存占用,可通过 FileRequestOptions.BufferSizeInBytes 调整

权限与路径处理:SMB 挂载和 SDK 访问不能混用

如果你同时在 Windows 上用 net use Z: mystorage.file.core.windows.netmyshare 挂载了共享,并在 C# 里也用 SDK 访问同一个共享,要注意两者路径语义不一致:SMB 挂载后路径是本地风格(Z: older ile.txt),SDK 是纯逻辑路径(folder/file.txt),且不支持 .. 向上遍历。

常见错误现象:用 SDK 创建了 logs/2024/06/app.log,但在挂载盘里看到 Z:logs%2F2024%2F06%2Fapp.log —— 这是因为 SDK 默认对路径做 URL 编码,而 SMB 客户端不处理编码。

  • 避免路径中出现空格、中文、#? 等特殊字符;SDK 会自动编码,但解码行为不保证跨平台一致
  • SDK 不支持硬链接、符号链接、ACL 继承等 NTFS 特性;所有权限靠存储账户级 SAS 或 RBAC 控制
  • 并发写同一文件无锁机制,SDK 不提供原子重命名或条件更新(IfExists 只用于存在性判断,非 CAS)

真正麻烦的不是怎么写代码,而是得时刻记住:这不是本地磁盘,它没有当前工作目录、没有文件句柄、没有缓存一致性保障。每次操作都是独立 HTTP 请求,失败重试策略、超时设置、连接复用这些细节,比语法更决定成败。

text=ZqhQzanResources