用 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、字段值为空就干脆不写——这些地方错一个,用户点开就失败,还很难定位。
