You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#中如何将PDF二进制字符串转为MS SQL varBinary(max)并调用存储过程

问题描述

在MS SQL查询中,我可以将PDF二进制字符串转换为varBinary(max)并插入,PDF能正常打开。但用C#调用MS SQL存储过程执行相同转换时,插入后的PDF无法打开,提示格式错误。以下是可正常运行的SQL代码及存在问题的C#代码,求解决建议。

可正常运行的SQL代码

Declare @ContentTest varbinary(max)
Declare @Doc varchar(max) 

-- PDF Binary字符串
Set @Doc = '0x255044462d312e340a25e2e3cfd30a332030206f626a0a3c3c2f54797065202f506167650a2.......';
SET @ContentTest = CONVERT(VARBINARY(max), @Doc, 1);

EXEC dbo.SP_AddDocument
    @UserID = 2,
    @Subject = "User Details Report",
    @Details = "Report",
    @DocType = "PDF",
    @Compression = 0,
    @Content = @ContentTest,
    @CorroDate = "2022-11-25 10:05:47",
    @RequiresCheck = 0;

存在问题的C#代码

public static async Task<string> syncDocumentToBPServer(JObject data)
{
    dbConnect();
    _sqlCon.Open();

    int lastInsertID = 0;
    int k = 0;

    if (_sqlCon.State == System.Data.ConnectionState.Open)
    {
        int bpPatientId = (int)data["bpPatientId"];
        String content = data["content_binary"].ToString();
        byte[] theBytes = Encoding.UTF8.GetBytes(content);

        string sql = @"DATABASE.dbo.[SP_AddDocument]";
        SqlCommand cmd = new SqlCommand(sql, _sqlCon);
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.Parameters.Add(new SqlParameter("@PatientID", bpPatientId));
        cmd.Parameters.Add(new SqlParameter("@Subject", "User Details Report"));
        cmd.Parameters.Add(new SqlParameter("@Details", "Report"));
        cmd.Parameters.Add(new SqlParameter("@DocType", "PDF"));
        cmd.Parameters.Add(new SqlParameter("@Compression", 0));
        cmd.Parameters.Add("@Content", SqlDbType.VarBinary, 1).Value = theBytes;
        cmd.Parameters.Add(new SqlParameter("@CorroDate", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")));
        cmd.Parameters.Add(new SqlParameter("@RequiresCheck", false));

        SqlParameter returnParameter = cmd.Parameters.Add("RecordID", SqlDbType.Int);
        returnParameter.Direction = ParameterDirection.ReturnValue;

        k = cmd.ExecuteNonQuery();
        if (k != 0)
        {
            lastInsertID = (int)returnParameter.Value;
        }
    }

    var result = new
    {
        success = k,
        recordId = lastInsertID,
    };
    _sqlCon.Close();

    return JsonConvert.SerializeObject(result);
}

解决建议

你的C#代码存在三个关键错误,直接导致PDF格式损坏:

  1. 二进制字符串转字节数组的逻辑错误
    SQL中CONVERT(VARBINARY(max), @Doc, 1)是把以0x开头的十六进制字符串直接解析为二进制数据,但你用Encoding.UTF8.GetBytes(content)是把整个十六进制字符串当作普通文本转字节,完全破坏了原始二进制结构。比如字符串里的0x25,SQL会转成单个字节0x25,而UTF8会转成0x30、0x78、0x32、0x35四个字节。

    正确转换方式:先去掉字符串开头的0x,再将十六进制字符串转为字节数组:

    String content = data["content_binary"].ToString();
    // 移除开头的0x标识
    if (content.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
    {
        content = content.Substring(2);
    }
    // 十六进制字符串转字节数组
    byte[] theBytes = Enumerable.Range(0, content.Length)
                                .Where(x => x % 2 == 0)
                                .Select(x => Convert.ToByte(content.Substring(x, 2), 16))
                                .ToArray();
    
  2. VarBinary参数长度设置错误
    你设置SqlDbType.VarBinary, 1意味着参数仅保留1字节,会截断大部分PDF数据。应去掉长度参数,或设置为-1表示varbinary(max):

    cmd.Parameters.Add("@Content", SqlDbType.VarBinary).Value = theBytes;
    // 或者明确指定max长度
    cmd.Parameters.Add("@Content", SqlDbType.VarBinary, -1).Value = theBytes;
    
  3. 日期参数传递方式优化
    将DateTime.Now转为字符串再传递可能引发格式解析问题,直接传入DateTime类型即可:

    cmd.Parameters.Add(new SqlParameter("@CorroDate", DateTime.Now));
    

内容的提问来源于stack exchange,提问作者Prashant Rajput

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 16:01:02