在 C# 中使用 vCard(VCF)文件

本文覆盖了 VCardContact 类来自 Aspose.Email.PersonalInfo.VCard 命名空间,独立于 Outlook 和 MAPI 读取和写入 vCard(VCF)文件。用于创建和管理 Outlook MapiContact 项目 — 也可以导出为 VCF — 参见 Outlook 联系人管理.

VCardContact 与 MapiContact

Aspose.Email 通过两个不同的类公开联系人,选择正确的类可避免大量混淆:

  • VCardContact (命名空间 Aspose.Email.PersonalInfo.VCard) — 纯 vCard 对象。当您的源和目标都是 vCard(VCF)文件且不需要 Outlook/MAPI 功能时使用。它直接读取和写入 VCF,支持 vCard 2.1/3.0/4.0,文件中多联系人,以及异步加载。
  • MapiContact (命名空间 Aspose.Email.Mapi) — Outlook 联系人。当您处理 MSG/PST 或需要 MAPI 特定属性时使用它。 MapiContact 也可以通过其 FromVCardSave 方法(参见 Outlook 联系人管理).

本文其余部分侧重于 VCardContact.

创建 vCard 并保存

VCardContact 类具有无参数构造函数,并公开诸如 IdentificationInfo, 组织, 电子邮件, TelephoneNumbers,以及 DeliveryAddresses.

以下代码片段展示了如何从头构建联系人并将其保存为 vCard(VCF)文件。

using Aspose.Email.PersonalInfo.VCard;

var contact = new VCardContact
{
    IdentificationInfo = new VCardIdentificationInfo
    {
        DisplayName = "Bertha Buell",
        FullName = "Bertha A. Buell",
        Nickname = "Bertie",
        Birthday = new DateTime(1980, 5, 20)
    },
    Organization = new VCardOrganization
    {
        Organization = "Awthentikz",
        Title = "Social work assistant"
    },
    Emails = new VCardEmailCollection
    {
        new VCardEmail
        {
            EmailAddress = "BerthaABuell@example.com",
            EmailType = VCardEmailType.INTERNET
        }
    }
};

// Save as a vCard (VCF) file
contact.Save("contact.vcf");

联系人属性模型

除了上述的姓名和电子邮件之外,一个 VCardContact 通过强类型属性集公开完整的 vCard 数据模型。下面的代码片段扩展了 contact 之前创建的。每个集合可以使用集合初始化器进行赋值或追加 Add.

邮政地址

邮政地址位于 DeliveryAddresses 集合为 VCardDeliveryAddress 项目。该 AddressType 属性接受以下组合 VCardDeliveryAddressType 标志(HOME, WORK, POSTAL, PARCEL, DOM, INTL, PREF).

contact.DeliveryAddresses = new VCardDeliveryAddressCollection
{
    new VCardDeliveryAddress
    {
        AddressType = VCardDeliveryAddressType.WORK | VCardDeliveryAddressType.PREF,
        Street = "4 Darwinia Loop",
        Locality = "Eighty Mile Beach",
        Region = "WA",
        PostalCode = "6725",
        CountryName = "Australia"
    }
};

电话号码

电话号码位于 TelephoneNumbers 集合为 VCardTelephoneNumber 项目。该 TelephoneType 属性接受以下组合 VCardTelephoneType 标志(VOICE, WORK, HOME, CELL, FAX, PAGER, PREF,以及更多)。

contact.TelephoneNumbers = new VCardTelephoneNumberCollection
{
    new VCardTelephoneNumber
    {
        TelephoneNumber = "(08) 9080 1183",
        TelephoneType = VCardTelephoneType.WORK | VCardTelephoneType.VOICE
    },
    new VCardTelephoneNumber
    {
        TelephoneNumber = "(925) 599 3355",
        TelephoneType = VCardTelephoneType.CELL
    }
};

地理位置

Geo 属性将全局位置存储为 float 纬度和经度。

contact.Geo = new VCardGeo
{
    Latitude = 48.858844f,
    Longitude = 2.294351f
};

照片

联系人照片设置在 IdentificationInfo.Photo 作为 VCardPhoto。它可以通过图像字节内嵌或通过 URL 引用。图像格式由 VCardPhotoType 以及存储模式通过 VCardValueLocation.

// Embed the image bytes inline
contact.IdentificationInfo.Photo = new VCardPhoto
{
    Data = File.ReadAllBytes("portrait.jpg"),
    PhotoType = VCardPhotoType.JPEG,
    ValueLocation = VCardValueLocation.INLINE
};

// Or reference an external image by URL
contact.IdentificationInfo.Photo = new VCardPhoto
{
    Uri = "https://example.com/portrait.jpg",
    PhotoType = VCardPhotoType.JPEG,
    ValueLocation = VCardValueLocation.URL
};

格式化地址标签

标签是已格式化、可直接打印的收件地址文本。标签位于 标签 集合为 VCardLabel 项目,每个都标记了地址类型。

contact.Labels = new VCardLabelCollection
{
    new VCardLabel
    {
        AddressType = VCardDeliveryAddressType.WORK,
        Address = "4 Darwinia Loop\r\nEighty Mile Beach WA 6725\r\nAustralia"
    }
};

读取模型返回

加载 vCard 后,相同的属性集会公开解析后的数据。

var loaded = VCardContact.Load("contact.vcf");

Console.WriteLine(loaded.IdentificationInfo?.DisplayName);

foreach (var address in loaded.DeliveryAddresses)
{
    Console.WriteLine($"{address.AddressType}: {address.Street}, {address.Locality}");
}

foreach (var phone in loaded.TelephoneNumbers)
{
    Console.WriteLine($"{phone.TelephoneType}: {phone.TelephoneNumber}");
}

if (loaded.Geo != null)
{
    Console.WriteLine($"Geo: {loaded.Geo.Latitude}, {loaded.Geo.Longitude}");
}

安全性(公钥或证书)

安全性 属性公开存储在 vCard 中的公钥或身份验证证书( KEY 属性)。它的 SaveToPEM 方法将该密钥写入 PEM 文件。

var signed = VCardContact.Load("signed.vcf");

if (signed.Security != null && signed.Security.Key != null)
{
    Console.WriteLine("Key type: " + signed.Security.Type);

    // Export the embedded public key / certificate to a PEM file
    signed.Security.SaveToPEM("public-key.pem");
}

加载 vCard

使用静态 VCardContact.Load 方法从文件或流读取 vCard。加载后,联系人的属性可通过创建时使用的相同属性集访问。

// Load from a file
var contact = VCardContact.Load("contact.vcf");
Console.WriteLine(contact.IdentificationInfo.DisplayName);

// Load from a stream
using (var stream = File.OpenRead("contact.vcf"))
{
    var fromStream = VCardContact.Load(stream);
}

使用特定编码加载

要控制读取时使用的文本编码,请传入 VCardLoadOptions 对象及其 PreferredEncoding 属性集。

var loadOptions = new VCardLoadOptions { PreferredEncoding = Encoding.UTF8 };
var contact = VCardContact.Load("contact.vcf", loadOptions);

从单个文件读取多个联系人

一个 vCard 文件可能包含多个联系人。使用静态 IsMultiContacts 方法以检查文件或流是否包含多个联系人,以及 LoadAsMultiple 将它们全部读取到一个 List<VCardContact>。两种方法都有文件、流和加载选项的重载:

  • static bool IsMultiContacts(string filePath) / IsMultiContacts(Stream stream)
  • static List<VCardContact> LoadAsMultiple(string filePath) / LoadAsMultiple(string filePath, VCardLoadOptions options)
  • static List<VCardContact> LoadAsMultiple(Stream stream) / LoadAsMultiple(Stream stream, VCardLoadOptions options)
using (var stream = new FileStream("contacts.vcf", FileMode.Open, FileAccess.Read))
{
    if (VCardContact.IsMultiContacts(stream))
    {
        List<VCardContact> contacts = VCardContact.LoadAsMultiple(stream);

        foreach (var contact in contacts)
        {
            Console.WriteLine(contact.IdentificationInfo.DisplayName);
        }
    }
}

异步加载联系人

对于大型联系人列表或 I/O 密集型应用程序(桌面、Web 或移动), VCardContact 提供不会阻塞调用线程的异步加载。使用 LoadAsync 用于单个联系人和 LoadAsMultipleAsync 适用于多个。两者都接受 CancellationToken.

// A single contact
var contact = await VCardContact.LoadAsync("contact.vcf", CancellationToken.None);
Console.WriteLine(contact.IdentificationInfo.DisplayName);

// Multiple contacts
var contacts = await VCardContact.LoadAsMultipleAsync(
    "contacts.vcf", new VCardLoadOptions(), CancellationToken.None);

foreach (var loaded in contacts)
{
    Console.WriteLine(loaded.IdentificationInfo.DisplayName);
}

保存选项

VCardSaveOptions 类自定义联系人写入方式:

  • Version —— 从中输出的 vCard 版本 VCardVersion 枚举: V21 (vCard 2.1,默认), V30 (3.0),或 V40 (4.0)。
  • PreferredTextEncoding —— 写入文件时使用的编码。
  • UseExtensions —— 是否扩展(X-) 属性可能被写入。默认是 true.
  • ProductId —— 写入的值到 PRODID 属性。
var contact = VCardContact.Load("contact.vcf");

var saveOptions = new VCardSaveOptions
{
    Version = VCardVersion.V30,             // write vCard 3.0 (default is V21)
    PreferredTextEncoding = Encoding.UTF8,  // encoding used when writing
    UseExtensions = true,                   // allow extended (X-) properties
    ProductId = "My Company"                // PRODID value
};

contact.Save("contact_v3.vcf", saveOptions);

另见