1
yangbin
2024-08-15 fc38e2635216775a80210d0df109dc6174d66813
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
package org.jeecg.modules.utils;
 
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.parser.PdfTextExtractor;
import org.jeecg.modules.ai.vo.ItemPosition;
import org.jeecg.modules.ai.vo.KeyWordPosition;
import org.jeecg.modules.ai.vo.KeyWordPositionVo;
import org.jeecg.modules.ai.vo.MyTextExtractionStrategy;
 
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
 
/**
 * @author clown
 * * @date 2024/7/23
 */
public class PdfUtils {
    /**
     * 用于供外部类调用获取关键字所在PDF文件坐标
     * @param filepath
     * @param keyWords
     * @return
     */
    public static List<KeyWordPosition> getKeyWordsByPath(String filepath, String keyWords) {
        List<KeyWordPosition> matchItems = null;
        try{
            PdfReader pdfReader = new PdfReader(filepath);
            matchItems = getKeyWords(pdfReader, keyWords);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return matchItems;
    }
 
    /**
     * 获取关键字所在PDF坐标
     * @param pdfReader
     * @param keyWords
     * @return
     */
    private static List<KeyWordPosition> getKeyWords(PdfReader pdfReader, String keyWords) {
        int page = 0;
 
        List<KeyWordPosition> matchItems = new ArrayList<>();
        try{
            int pageNum = pdfReader.getNumberOfPages();
            StringBuilder allText = null;
 
            //遍历页
            for (page = 1; page <= pageNum; page++) {
                //只记录当页的所有内容,需要记录全部页放在循环外面
                List<ItemPosition> allItems = new ArrayList<>();
                //扫描内容
                MyTextExtractionStrategy myTextExtractionStrategy = new MyTextExtractionStrategy(allItems, page);
                PdfTextExtractor.getTextFromPage(pdfReader, page, myTextExtractionStrategy);
                //当页的文字内容,用于关键词匹配
                allText = new StringBuilder();
                //一个字一个字的遍历
                for (int i=0; i<allItems.size(); i++) {
                    ItemPosition item = allItems.get(i);
                    allText.append(item.getText());
                    //关键字存在连续多个块中
                    if(allText.indexOf(keyWords) != -1) {
                        KeyWordPosition keyWordPosition = new KeyWordPosition();
                        //记录关键词每个字的位置,只记录开始结束标记时会有问题
                        List<ItemPosition> listItem = new ArrayList<>();
                        for(int j=i-keyWords.length()+1; j<=i; j++) {
                            listItem.add(allItems.get(j));
                        }
                        keyWordPosition.setListItem(listItem);
                        keyWordPosition.setText(keyWords);
                        matchItems.add(keyWordPosition);
                        allText.setLength(0);
                    }
                }
 
 
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return matchItems;
    }
 
 
 
 
    public static void main(String[] args) throws Exception {
        String keyword = "一旦发生机床安全事故";
        String sourcePdf = "F:\\123.pdf";
        String watermarkPdf = "F:\\12_bak.pdf";
        Long start = System.currentTimeMillis();
        System.out.println("开始扫描....");
        List<KeyWordPosition> matchItems = getKeyWordsByPath(sourcePdf, keyword);
        System.out.println(matchItems);
        System.out.println("扫描结束["+(System.currentTimeMillis()-start)+"ms],共找到关键字["+keyword+"]出现["+matchItems.size()+"]次");
        start = System.currentTimeMillis();
        System.out.println("开始添加标记....");
        andRectangleMark(sourcePdf
                , watermarkPdf
                , matchItems
                , BaseColor.RED
                , 2
                , 2);
        //文件整理
        System.out.println("标记添加完成["+(System.currentTimeMillis()-start)+"ms]");
 
    }
 
 
    public static List<KeyWordPositionVo> findListWord(String sourcePath, String keyWord){
        System.out.println("开始扫描....");
        try {
            List<KeyWordPositionVo> matchItems = getKeyWordsByPathOne(sourcePath, keyWord);
            return matchItems;
        }catch (Exception e) {
            return null;
        }
    }
 
    /**
     * 用于供外部类调用获取关键字所在PDF文件坐标
     * @param filepath
     * @param keyWords
     * @return
     */
    public static List<KeyWordPositionVo> getKeyWordsByPathOne(String filepath, String keyWords) {
        List<KeyWordPositionVo> matchItems = null;
        try{
            PdfReader pdfReader = new PdfReader(filepath);
            matchItems = getKeyWordPage(pdfReader, keyWords);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return matchItems;
    }
 
    /**
     * 获取关键字所在PDF坐标 一页只取第一条
     * @param pdfReader
     * @param keyWords
     * @return
     */
    private static List<KeyWordPositionVo> getKeyWordPage(PdfReader pdfReader, String keyWords) {
        int page = 0;
        List<KeyWordPositionVo> matchItems = new ArrayList<>();
        try{
            int pageNum = pdfReader.getNumberOfPages();
            StringBuilder allText = null;
            //遍历页
            for (page = 1; page <= pageNum; page++) {
                //只记录当页的所有内容,需要记录全部页放在循环外面
                List<ItemPosition> allItems = new ArrayList<>();
                //扫描内容
                MyTextExtractionStrategy myTextExtractionStrategy = new MyTextExtractionStrategy(allItems, page);
                PdfTextExtractor.getTextFromPage(pdfReader, page, myTextExtractionStrategy);
                //当页的文字内容,用于关键词匹配
                allText = new StringBuilder();
                //一个字一个字的遍历
                for (int i=0; i<allItems.size(); i++) {
                    ItemPosition item = allItems.get(i);
                    allText.append(item.getText());
                    //关键字存在连续多个块中
                    if(allText.indexOf(keyWords) != -1) {
                        KeyWordPosition keyWordPosition = new KeyWordPosition();
                        //记录关键词每个字的位置,只记录开始结束标记时会有问题
                        KeyWordPositionVo vo = new KeyWordPositionVo();
                        for(int j=i-keyWords.length()+1; j<=i; j++) {
                            if (allItems.get(j).getText().indexOf(keyWords)!= -1) {
                                vo.setPage(allItems.get(j).getPage());
                                vo.setRectangle(allItems.get(j).getRectangle());
                                vo.setText(allItems.get(j).getText());
                                vo.setRectangleString(allItems.get(j).getRectangle().toString());
                                matchItems.add(vo);
                                break;
                            }
                        }
                        break;
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return matchItems;
    }
 
    /**
     * 添加矩形标记
     * @param oldPath
     * @param newPath
     * @param matchItems 关键词
     * @param color 标记颜色
     * @param lineWidth 线条粗细
     * @param padding 边框内边距
     * @throws DocumentException
     * @throws IOException
     */
    public static void andRectangleMark(String oldPath, String newPath, List<KeyWordPosition> matchItems, BaseColor color, int lineWidth, int padding) throws DocumentException, IOException{
        // 待加水印的文件
        PdfReader reader = new PdfReader(oldPath);
        // 加完水印的文件
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(newPath));
 
        PdfContentByte content;
 
        // 设置字体
        // 循环对每页插入水印
        for (KeyWordPosition keyWordPosition:matchItems)
        {
            //一个关键词的所有字坐标
            List<ItemPosition> oneKeywordItems = keyWordPosition.getListItem();
            for(int i=0; i<oneKeywordItems.size(); i++) {
                ItemPosition item = oneKeywordItems.get(i);
                ItemPosition preItem = i==0?null:oneKeywordItems.get(i-1);
                //带确实是否水印
 
                // 水印的起始
                content = stamper.getOverContent(item.getPage());
                // 开始写入水印
                content.setLineWidth(lineWidth);
                content.setColorStroke(color);
                System.out.println(item.toString());
 
                //底线
                content.moveTo(item.getRectangle().getLeft()-padding, item.getRectangle().getBottom()-padding);
                content.lineTo(item.getRectangle().getRight()+padding, item.getRectangle().getBottom()-padding);
                if(i!=0 && preItem!=null && (preItem.getRectangle().getBottom()-padding)==(item.getRectangle().getBottom()-padding) && (preItem.getRectangle().getRight()+padding)!=(item.getRectangle().getLeft()-padding)) {
                    content.moveTo(preItem.getRectangle().getRight()+padding, preItem.getRectangle().getBottom()-padding);
                    content.lineTo(item.getRectangle().getLeft()-padding, item.getRectangle().getBottom()-padding);
                }
                //上线
                content.moveTo(item.getRectangle().getLeft()-padding, item.getRectangle().getTop()+padding);
                content.lineTo(item.getRectangle().getRight()+padding, item.getRectangle().getTop()+padding);
                if(i!=0 && preItem!=null && (preItem.getRectangle().getTop()+padding)==(item.getRectangle().getTop()+padding) && (preItem.getRectangle().getRight()+padding)!=(item.getRectangle().getLeft()-padding)) {
                    content.moveTo(preItem.getRectangle().getRight()+padding, preItem.getRectangle().getTop()+padding);
                    content.lineTo(item.getRectangle().getLeft()-padding, item.getRectangle().getTop()+padding);
                }
 
                //左线
                if(i==0) {
                    content.moveTo(item.getRectangle().getLeft()-padding, item.getRectangle().getBottom()-padding);
                    content.lineTo(item.getRectangle().getLeft()-padding, item.getRectangle().getTop()+padding);
                }
                //右线
                if(i==(oneKeywordItems.size()-1)) {
                    content.moveTo(item.getRectangle().getRight()+padding, item.getRectangle().getBottom()-padding);
                    content.lineTo(item.getRectangle().getRight()+padding, item.getRectangle().getTop()+padding);
                }
 
                content.stroke();
            }
        }
        stamper.close();
    }
}