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

C# 如何将Web Service返回的byte[]格式PDF在新标签页打开

问题根因

  1. 第一种方案用Ajax请求PDF二进制流时,Ajax默认将响应按文本解析,导致输出乱码,且ASMX服务的JSON序列化配置会干扰二进制流输出。
  2. 第二种方案直接将返回的data.d塞入Blob导致文件损坏,是因为ASMX服务会自动将返回的byte[]序列化为Base64字符串,而非原始二进制数据,直接输入Blob会导致编码不匹配。
  3. 原有Ajax请求的URL中id参数额外包裹了单引号,会导致传入后端的id值带单引号,数据库查询匹配失败。

后端调整(二选一即可)

方案1(推荐):直接输出二进制流,适配浏览器直接访问

无需走Ajax,让浏览器原生处理PDF渲染,后端代码调整如下:

// 去掉Json序列化配置,直接操作Response输出
[WebMethod]
[ScriptMethod(UseHttpGet = true)]
public void RetrieveSPODData(string id)
{
    string query = @"Select * from dcmnts where BUSNSS_ID = :BUSNSS_ID";
    byte[] data = null;
    string ConnString = ConfigurationManager.ConnectionStrings["DbConnEnc"].ToString();

    using (OracleConnection connection = new OracleConnection(BaseEncryptor.DecryptString(ConnString)))
    {
        OracleCommand command = null;
        OracleDataAdapter adapter = null;
        try
        {
            if (connection.State != ConnectionState.Open)
                connection.Open();
            command = new OracleCommand(query, connection);
            command.Parameters.Add(new OracleParameter("BUSNSS_ID", id.Trim('\''))); // 兼容原有错误的单引号传参,前端去掉单引号后可删除Trim逻辑
            adapter = new OracleDataAdapter(command);
            DataTable dataTable = new DataTable();
            adapter.Fill(dataTable);

            if (dataTable.Rows.Count > 0)
            {
                data = dataTable.Rows[0].Field<byte[]>("SUMMARY_SPOD");
            }
            // 空数据处理
            if (data == null || data.Length == 0)
            {
                HttpContext.Current.Response.StatusCode = 404;
                HttpContext.Current.Response.End();
                return;
            }

            HttpContext.Current.Response.ClearHeaders();
            HttpContext.Current.Response.AddHeader("Content-Disposition", "inline;filename=file.pdf");
            HttpContext.Current.Response.ContentType = "application/pdf";
            HttpContext.Current.Response.BinaryWrite(data);
            HttpContext.Current.Response.Flush();
            HttpContext.Current.Response.End();
        }
        finally
        {
            adapter?.Dispose();
            command?.Dispose();
        }
    }
}

同时要在web.config中开启ASMX的GET请求权限:

<system.web>
  <webServices>
    <protocols>
      <add name="HttpGet"/>
    </protocols>
  </webServices>
</system.web>

方案2:返回Base64编码,适配Ajax请求

后端直接返回byte[],ASMX会自动转为Base64字符串,代码调整如下:

[ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true)]
[WebMethod]
public byte[] RetrieveSPODData(string id)
{
    string query = @"Select * from dcmnts where BUSNSS_ID = :BUSNSS_ID";
    string ConnString = ConfigurationManager.ConnectionStrings["DbConnEnc"].ToString();

    using (OracleConnection connection = new OracleConnection(BaseEncryptor.DecryptString(ConnString)))
    {
        OracleCommand command = null;
        OracleDataAdapter adapter = null;
        try
        {
            if (connection.State != ConnectionState.Open)
                connection.Open();
            command = new OracleCommand(query, connection);
            command.Parameters.Add(new OracleParameter("BUSNSS_ID", id.Trim('\'')));
            adapter = new OracleDataAdapter(command);
            DataTable dataTable = new DataTable();
            adapter.Fill(dataTable);

            if (dataTable.Rows.Count > 0)
            {
                return dataTable.Rows[0].Field<byte[]>("SUMMARY_SPOD");
            }
            return Array.Empty<byte>();
        }
        finally
        {
            adapter?.Dispose();
            command?.Dispose();
        }
    }
}

前端调整(对应后端方案二选一)

对应后端方案1(最简便,无弹窗拦截问题)

完全不需要Ajax和JS方法,直接修改a标签即可:

<a href="Services/MyService.asmx/RetrieveSPODData?id=<%=TransportationDocument != null ? TransportationDocument.BusinessID.ToString() : String.Empty %>" target="_blank">
    <img alt="SPOD" src="images/icons/adobe_acrobat_icon.png">
</a>

对应后端方案2(必须走Ajax的场景)

调整JS代码,将Base64字符串转为二进制后再生成Blob:

function getSPOD(id) {
    $.ajax({
        type: "GET",
        // 去掉id参数外面的单引号
        url: `Services/MyService.asmx/RetrieveSPODData?id=${id}`,
        contentType: 'application/json; charset=utf-8',
        success: function (data) {
            if (!data.d || data.d.length === 0) {
                alert("未找到对应PDF文件");
                return;
            }
            // Base64转二进制
            const binaryStr = atob(data.d);
            const byteArray = new Uint8Array(binaryStr.length);
            for (let i = 0; i < binaryStr.length; i++) {
                byteArray[i] = binaryStr.charCodeAt(i);
            }
            const file = new Blob([byteArray], { type: 'application/pdf' });
            const fileURL = URL.createObjectURL(file);
            window.open(fileURL);
        },
        error: function (textStatus, errorThrown) {
            console.log(textStatus, errorThrown);
        }
    });
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 13:24:03