用 stringbuilder 拼接 vcard 4.0 最稳妥,需严格遵循字段顺序、utf-8 编码、crlf 换行、ascii 文件名及非空字段省略规则。

用 StringBuilder 拼接 vCard 4.0 标准文本最稳妥
vCard 不是二进制格式,本质是纯文本(UTF-8 编码),C# 里直接用 StringBuilder 按规范拼字符串即可,无需第三方库。关键在于严格遵循字段顺序、转义规则和换行符(\r\n)。常见错误是漏掉 VERSION:3.0 或 END:VCARD,或对含逗号/分号的姓名、邮箱未做 QUOTED-PRINTABLE 编码(其实 vCard 4.0 推荐用 UTF-8 + 行折叠,但多数手机仍兼容 3.0 的简单转义)。
实操建议:
- 开头固定写
BEGIN:VCARD\r\nVERSION:3.0\r\n(iOS/Android 识别最稳) - 姓名字段用
N:Last;First;Middle;;\r\nFN:First Middle Last\r\n,注意分号分隔姓/名/中间名,末尾两个分号不能少 - 邮箱、电话必须带类型参数,如
EMAIL;TYPE=WORK:dev@example.com\r\nTEL;TYPE=CELL:+8613800138000\r\n - 地址字段用
ADR;TYPE=HOME:;;Street 123;City;State;100000;CN\r\n,各段用分号分隔,空段留空但分号保留 - 所有值含换行、逗号、分号时,需用
=转义:换行→=0D=0A,逗号→=2C,分号→=3B(但实际中多数读取器容忍不转义,仅当解析失败时再加)
File.WriteAllText 保存时必须指定 Encoding.UTF8
Windows 默认 File.WriteAllText 用 UTF-8 without BOM,这恰好是 vCard 要求的编码。但若手动指定 Encoding.Default 或 Encoding.GetEncoding("GB2312"),中文会乱码——微信、iPhone 短信里点开直接显示问号。
实操建议:
- 保存路径用
.vcf后缀,如path = @"C:\temp\contact.vcf" - 调用
File.WriteAllText(path, vcardContent, Encoding.UTF8),显式传参,别依赖默认 - 避免用
StreamWriter且未设Encoding,容易隐式走系统区域设置 - 生成后可用记事本“另存为”确认编码是否为 UTF-8(无签名),或用 VS Code 底部状态栏看编码标识
微信/QQ/邮件附件发 vCard,文件名别含空格或中文
移动端微信转发 .vcf 文件时,如果文件名是 张三名片.vcf 或 my contact.vcf,iOS 往往无法识别为电子名片,点开就当普通文本;Android 部分机型也会提示“不支持的文件类型”。根本原因是 MIME 类型协商失败,而文件名是触发条件之一。
实操建议:
- 文件名只用 ASCII 字母、数字、下划线、短横线,如
contact_zhangsan.vcf或user_123.vcf - 发送邮件时,在
Attachment中显式设置ContentType:new ContentType("text/vcard") - 微信内测试:先发给自己,点开确认出现“添加到通讯录”按钮,而非“用其他应用打开”
- 若需批量生成,文件名用 GUID 哈希前 8 位(如
5a7b2c1e.vcf),彻底规避命名问题
字段缺失时不要留空行,用注释代替或直接省略
vCard 解析器对空字段敏感。比如写了 TEL;\r\n(后面没值),某些 Android 厂商定制 ROM 会崩溃;又或者 PHOTO; 后跟空值,iOS 可能拒绝导入。这不是标准问题,而是实现差异。
实操建议:
- 只写业务上真实存在的字段,不确定的(如
ORG、TITLE)直接跳过,别留占位符 - 若需标记“该字段暂无”,用
X-NO-ORG:1\r\n这类自定义扩展字段(以X-开头),标准解析器会忽略 - 照片不嵌入 base64(体积大、易出错),优先用
PHOTO;VALUE=URI:https://example.com/photo.jpg\r\n - 测试时用 iOS 自带“通讯录”App 导入,它报错最严格,能提前暴露字段格式问题
vCard 表面简单,但跨平台兼容性卡点全在细节:换行符必须 \r\n、编码必须 UTF-8 无 BOM、文件名必须 ASCII、字段值为空就干脆不写——这些地方错一个,用户点开就失败,还很难定位。










