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

C#实现服务器URL对应PDF文件逐行内容读取的方法

C# 从远程PDF流逐行提取文本实现方案

你现在拿到的是PDF二进制流,没法直接用普通文本流的ReadLine方法读出行内容——PDF本身是结构化二进制格式,没有原生“行”的概念,所有文本都是带坐标的独立块,必须用专门的解析库处理,推荐用开源无依赖的PdfPig,不需要把PDF存本地,直接对接你已经拿到的内存流就能解析。

实现步骤

  • 首先给项目安装Nuget包:PdfPig
  • 拿到PDF响应流后先做响应校验,避免把鉴权失败返回的HTML内容当PDF解析
  • PDF坐标原点在页面左下角,纵向Y坐标差值在阈值内的文本属于同一行,按坐标分组、同组内按横向X坐标从左到右拼接,就能得到符合阅读顺序的逐行内容
  • 提取到的逐行文本直接存入集合,后续导出Excel直接遍历集合即可

完整可运行代码

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using UglyToad.PdfPig;
using UglyToad.PdfPig.Content;

public class Program
{
    // 全局静态HttpClient,避免重复实例化导致端口耗尽
    private static readonly HttpClient client = new HttpClient();
    public static async Task Main()
    {
        var pdfUrl = "你后续替换成最新的有效PDF地址即可";
        var response = await client.GetAsync(pdfUrl);
        // 校验请求是否成功,失败直接抛出异常,避免解析错误内容
        response.EnsureSuccessStatusCode();
        
        using (var stream = await response.Content.ReadAsStreamAsync())
        using (var pdfDocument = PdfDocument.Open(stream))
        {
            List<string> allPdfLines = new List<string>();
            // 遍历PDF所有页面
            foreach (var page in pdfDocument.GetPages())
            {
                // 行判定阈值:Y坐标差小于5像素判定为同一行,可根据PDF实际排版调整
                const double lineThreshold = 5;
                var words = page.GetWords().OrderByDescending(w => w.BoundingBox.Bottom).ToList();
                
                if (!words.Any())
                {
                    Console.WriteLine($"第{page.Number}页无文本层,可能是扫描件,需要加OCR逻辑才能提取内容");
                    continue;
                }

                // 按行分组拼接
                var currentLineBaseY = words[0].BoundingBox.Bottom;
                List<Word> currentLineWords = new List<Word> { words[0] };
                for (int i = 1; i < words.Count; i++)
                {
                    var word = words[i];
                    if (Math.Abs(word.BoundingBox.Bottom - currentLineBaseY) <= lineThreshold)
                    {
                        currentLineWords.Add(word);
                    }
                    else
                    {
                        // 同一行内按从左到右顺序拼接文本
                        var lineText = string.Join(" ", currentLineWords.OrderBy(w => w.BoundingBox.Left).Select(w => w.Text));
                        allPdfLines.Add(lineText);
                        // 逐行打印
                        Console.WriteLine(lineText);
                        // 重置行缓存
                        currentLineBaseY = word.BoundingBox.Bottom;
                        currentLineWords = new List<Word> { word };
                    }
                }
                // 处理页面最后一行
                if (currentLineWords.Any())
                {
                    var lastLineText = string.Join(" ", currentLineWords.OrderBy(w => w.BoundingBox.Left).Select(w => w.Text));
                    allPdfLines.Add(lastLineText);
                    Console.WriteLine(lastLineText);
                }
            }
            // 此处allPdfLines就是存储了PDF所有行内容的集合,直接传入Excel导出逻辑即可
        }
    }
}

注意事项

  • 如果运行时报PDF格式错误,先把流存为本地文件确认内容是否为真的PDF,部分地址会做鉴权拦截返回登录页、错误页的HTML内容,会导致解析失败
  • 行判定阈值lineThreshold可根据你的PDF实际行间距调整,数值越大越容易把上下距离近的文本判定为同一行
  • 你提到的URL3小时失效问题,后续只需要替换pdfUrl变量的值即可,解析逻辑不需要改动

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 11:09:14