跳到主要内容

文件传输 (OpcUaFile)

概述

OPC UA Part 5 §10 定义 FileType (i=11575) 标准对象, 暴露 6 个 Method: Open / Read / Write / Close / GetPosition / SetPosition

OpcUaFile 把这 6 个 Method 封装为面向流式调用的 .NET API, 适用场景:

  • 固件升级 (PLC / IO / Drive 镜像下载)
  • 配方 (Recipe) 上传 / 下载
  • 任意文件镜像同步

对应规范段: Part 5 §10 (FileType)。

API

方法 / 属性类别读写说明
new OpcUaFile(ua, fileNodeId)构造绑定到服务端某个 FileType 实例
file.Size属性文件大小 (UInt64)
file.Writable属性是否可写 (Boolean)
file.UserWritable属性当前用户是否可写 (Boolean)
file.OpenCount属性当前打开句柄数 (UInt16)
file.Open(mode)方法打开句柄, 返回 fileHandle
file.Read(length)方法读取 N 字节
file.Write(bytes)方法写入字节
file.GetPosition()方法当前文件指针
file.SetPosition(pos)方法设置文件指针
file.Close()方法关闭句柄 (Dispose 自动调)
file.DownloadTo(localPath, progress)高层一键下载到本地文件
file.UploadFrom(localPath, progress)高层一键从本地文件上传

相关结构:

[Flags]
public enum FileOpenMode : byte
{
Read = 0x01, // 读
Write = 0x02, // 写
EraseExisting = 0x04, // 清空 (与 Write 组合)
Append = 0x08 // 追加 (打开后自动 SeekToEnd)
}

代码示例

using DarraOpcUa_Client;

using var ua = new DarraOpcUa("opc.tcp://device:4840");
ua.Connect();

// 1) 一键下载固件
using (var file = new OpcUaFile(ua, "ns=2;s=Firmware.Image"))
{
Console.WriteLine($"Size = {file.Size} bytes");
var rc = file.DownloadTo(@"C:\dl\firmware.bin",
new Progress<(ulong d, ulong t)>(p =>
Console.Write($"\r{p.d * 100 / p.t}% ({p.d}/{p.t})")));
if (rc != StatusCode.Good) Console.WriteLine($"\n下载失败: {rc}");
}

// 2) 一键上传配方 (清空后写)
using (var f2 = new OpcUaFile(ua, "ns=2;s=Recipe.Current"))
{
var rc = f2.UploadFrom(@"C:\recipes\new.csv");
if (rc != StatusCode.Good) Console.WriteLine($"上传失败: {rc}");
}

// 3) 手动流式读 (大文件分块自定义处理)
using (var f3 = new OpcUaFile(ua, "ns=2;s=Logs.Current"))
{
f3.Open(FileOpenMode.Read);
while (true)
{
var (st, chunk) = f3.Read(4096);
if (st != StatusCode.Good || chunk == null || chunk.Length == 0) break;
ProcessChunk(chunk);
}
f3.Close();
}

错误处理

  • 业务级失败 → 返回 StatusCode (BadInvalidArgument / BadUserAccessDenied / BadNotWritable / ...)
  • transport 失败 → throw OpcUaException
  • using 退出 / 异常路径 → 自动 Close 已打开的句柄 (实现 IDisposable)

实现说明

  • 块大小默认 4 KB (大多数 Server 限 8 KB 以内, 留余量)
  • ByteString 走 ISO-8859-1 字符串桥接, 无损保留 0x00-0xFF 全字节
  • Method NodeId 解析: 优先 TranslateBrowsePaths 找实例 Method, 失败 fallback 类级 NodeId (i=11580 等)

最佳实践

  • 始终用 using — 漏 Close 会让服务端句柄表泄漏
  • 进度回调切 UI 线程Progress<T> 默认捕获当前 SynchronizationContext, WPF/WinForms 调用方在 UI 线程构造即可
  • 大文件考虑分段重试 — 上层在每个 4KB 块边界做 checkpoint, 网络断后续传
  • 不要并发同一 fileHandle — 一个 Open 对应一个串行流

跨语言对照

C#PythonJavaC++RustC
OpcUaFileOpcUaFileOpcUaFileOpcUaFileOpcUaFileDarraUa_File_*
DownloadTodownload_todownloadToDownloadTodownload_toDarraUa_File_DownloadTo
UploadFromupload_fromuploadFromUploadFromupload_fromDarraUa_File_UploadFrom

下一步