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

如何在C#中从SOAP响应提取PDF附件到本地文件夹?

解决C#从multipart/related格式SOAP响应提取gzip压缩PDF附件的问题

问题根源

  • 误用ZipArchive处理gzip压缩流:gzip是单文件压缩格式,并非多文件zip归档,用ZipArchive解析会触发「不支持的压缩方法」异常
  • 未正确拆分multipart/related响应:需要先按响应头里的边界分割内容,定位到包含PDF的gzip压缩块

修正后的完整代码

using System;
using System.IO;
using System.IO.Compression;
using System.Net.Http;
using System.Text;

public class SoapPdfExtractor
{
    public async System.Threading.Tasks.Task ExtractPdfFromSoapResponse(HttpResponseMessage response)
    {
        // 1. 从响应头获取multipart边界
        var contentType = response.Content.Headers.ContentType;
        var boundary = contentType.Parameters.Find(p => p.Name.Equals("boundary", StringComparison.OrdinalIgnoreCase))?.Value;
        if (string.IsNullOrEmpty(boundary))
            throw new InvalidOperationException("无法获取multipart/related的边界值");

        // 2. 读取完整响应内容
        var responseContent = await response.Content.ReadAsStringAsync();
        var boundaryDelimiter = $"--{boundary}";

        // 3. 拆分multipart块,定位到gzip压缩的PDF部分
        var parts = responseContent.Split(new[] { boundaryDelimiter }, StringSplitOptions.RemoveEmptyEntries);
        foreach (var part in parts)
        {
            // 检查当前块是否包含gzip压缩的PDF(根据Content-Type判断)
            if (part.Contains("Content-Type: application/x-gzip") || part.Contains("Content-Encoding: gzip"))
            {
                // 提取块中的二进制内容(跳过头部,找到空行后的内容)
                var contentStartIndex = part.IndexOf("\r\n\r\n", StringComparison.Ordinal) + 4;
                if (contentStartIndex >= part.Length)
                    continue;

                var gzipBytes = Encoding.ASCII.GetBytes(part.Substring(contentStartIndex));
                
                // 4. 用GZipStream解压gzip流
                using var gzipStream = new GZipStream(new MemoryStream(gzipBytes), CompressionMode.Decompress);
                using var pdfStream = new MemoryStream();
                await gzipStream.CopyToAsync(pdfStream);
                
                // 5. 保存PDF到下载文件夹
                var downloadPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Downloads", "extracted.pdf");
                await File.WriteAllBytesAsync(downloadPath, pdfStream.ToArray());
                Console.WriteLine($"PDF已保存至: {downloadPath}");
                break;
            }
        }
    }
}

关键细节说明

  • 边界解析:从Content-Type头的boundary参数获取分割符,确保正确拆分multipart块
  • 内容定位:每个multipart块包含头部和内容,通过空行(\r\n\r\n)分割头部与二进制内容,避免把HTTP头混入压缩流
  • gzip解压:使用GZipStream处理单文件gzip压缩,这是gzip格式的正确处理方式,不要用ZipArchive
  • 路径处理:使用Environment.SpecialFolder.UserProfile获取系统下载文件夹路径,保证跨平台兼容性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 13:32:07