Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vehicle-quality-review
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
王飞
vehicle-quality-review
Commits
8840ebf2
Commit
8840ebf2
authored
Jan 18, 2024
by
盖献康
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
导出PDF-demo
parent
53f70cb0
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
345 additions
and
3 deletions
+345
-3
BookService.java
...y-review/src/main/java/com/ruoyi/service/BookService.java
+18
-0
BookServiceImpl.java
...src/main/java/com/ruoyi/service/impl/BookServiceImpl.java
+186
-0
BookController.java
...ty-review/src/main/java/com/ruoyi/web/BookController.java
+18
-0
STSong.TTF
quality-review/src/main/resources/fonts/STSong.TTF
+0
-0
receipt_template.pdf
...y-review/src/main/resources/template/receipt_template.pdf
+0
-0
pom.xml
ruoyi-common/pom.xml
+14
-3
PdfUtils.java
...common/src/main/java/com/ruoyi/common/utils/PdfUtils.java
+109
-0
No files found.
quality-review/src/main/java/com/ruoyi/service/BookService.java
View file @
8840ebf2
package
com
.
ruoyi
.
service
;
import
com.itextpdf.text.Document
;
import
com.ruoyi.domain.Book
;
import
com.baomidou.mybatisplus.extension.service.IService
;
import
org.apache.skywalking.apm.toolkit.trace.Tag
;
import
org.apache.skywalking.apm.toolkit.trace.Tags
;
import
org.apache.skywalking.apm.toolkit.trace.Trace
;
import
javax.servlet.http.HttpServletResponse
;
import
java.io.OutputStream
;
import
java.util.List
;
/**
...
...
@@ -19,4 +22,19 @@ public interface BookService extends IService<Book> {
List
<
Book
>
selectBookListException
(
String
name
);
/**
* 生成PDF
* @param os
* @return
* @throws Exception
*/
Document
generateItextPdfDocument
(
OutputStream
os
)
throws
Exception
;
/**
* 以模板生成
* @param response
* @throws Exception
*/
void
generateTempPDF
(
HttpServletResponse
response
)
throws
Exception
;
}
quality-review/src/main/java/com/ruoyi/service/impl/BookServiceImpl.java
View file @
8840ebf2
package
com
.
ruoyi
.
service
.
impl
;
import
com.baomidou.mybatisplus.extension.service.impl.ServiceImpl
;
import
com.itextpdf.text.*
;
import
com.itextpdf.text.pdf.*
;
import
com.itextpdf.text.pdf.codec.Base64
;
import
com.ruoyi.common.exception.ServiceException
;
import
com.ruoyi.common.utils.PdfUtils
;
import
com.ruoyi.domain.Book
;
import
com.ruoyi.service.BookService
;
import
com.ruoyi.mapper.BookMapper
;
...
...
@@ -9,9 +13,19 @@ import org.apache.skywalking.apm.toolkit.trace.Tag;
import
org.apache.skywalking.apm.toolkit.trace.Tags
;
import
org.apache.skywalking.apm.toolkit.trace.Trace
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.core.io.ClassPathResource
;
import
org.springframework.core.io.Resource
;
import
org.springframework.stereotype.Service
;
import
javax.servlet.ServletOutputStream
;
import
javax.servlet.http.HttpServletResponse
;
import
java.io.ByteArrayOutputStream
;
import
java.io.IOException
;
import
java.io.OutputStream
;
import
java.util.ArrayList
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
/**
* @author wangfei
...
...
@@ -38,6 +52,178 @@ public class BookServiceImpl extends ServiceImpl<BookMapper, Book> implements Bo
}
return
null
;
}
@Override
public
Document
generateItextPdfDocument
(
OutputStream
os
)
throws
Exception
{
// document
Document
document
=
new
Document
(
PageSize
.
A4
);
PdfWriter
.
getInstance
(
document
,
os
);
// open
document
.
open
();
// add content - pdf meta information
document
.
addAuthor
(
"pdai"
);
document
.
addCreationDate
();
document
.
addTitle
(
"pdai-pdf-itextpdf"
);
document
.
addKeywords
(
"pdf-pdai-keyword"
);
document
.
addCreator
(
"pdai"
);
// add content - page content
// Title
document
.
add
(
PdfUtils
.
createTitle
(
"Java 全栈知识体系"
));
// Chapter 1
document
.
add
(
PdfUtils
.
createChapterH1
(
"1. 知识准备"
));
document
.
add
(
PdfUtils
.
createChapterH2
(
"1.1 什么是POI"
));
document
.
add
(
PdfUtils
.
createParagraph
(
"Apache POI 是创建和维护操作各种符合Office Open XML(OOXML)标准和微软的OLE 2复合文档格式(OLE2)的Java API。用它可以使用Java读取和创建,修改MS Excel文件.而且,还可以使用Java读取和创建MS Word和MSPowerPoint文件。更多请参考[官方文档](https://poi.apache.org/index.html)"
));
document
.
add
(
PdfUtils
.
createChapterH2
(
"1.2 POI中基础概念"
));
document
.
add
(
PdfUtils
.
createParagraph
(
"生成xls和xlsx有什么区别?POI对Excel中的对象的封装对应关系?"
));
// Chapter 2
document
.
add
(
PdfUtils
.
createChapterH1
(
"2. 实现案例"
));
document
.
add
(
PdfUtils
.
createChapterH2
(
"2.1 用户列表示例"
));
document
.
add
(
PdfUtils
.
createParagraph
(
"以导出用户列表为例"
));
// 表格
PdfPTable
table
=
new
PdfPTable
(
new
float
[]{
20
,
40
,
50
,
40
,
40
});
table
.
setTotalWidth
(
500
);
table
.
setLockedWidth
(
true
);
table
.
setHorizontalAlignment
(
Element
.
ALIGN_CENTER
);
table
.
getDefaultCell
().
setBorder
(
1
);
for
(
int
i
=
0
;
i
<
5
;
i
++)
{
table
.
addCell
(
PdfUtils
.
createCell
(
"1"
));
table
.
addCell
(
PdfUtils
.
createCell
(
"2"
));
table
.
addCell
(
PdfUtils
.
createCell
(
"3"
));
table
.
addCell
(
PdfUtils
.
createCell
(
"4"
));
table
.
addCell
(
PdfUtils
.
createCell
(
"5"
));
}
document
.
add
(
table
);
document
.
add
(
PdfUtils
.
createChapterH2
(
"2.2 图片导出示例"
));
document
.
add
(
PdfUtils
.
createParagraph
(
"以导出图片为例"
));
// 图片
Image
image
=
Image
.
getInstance
(
"C:/Users/gxk/Pictures/Saved Pictures/nvm.png"
);
image
.
setAlignment
(
Element
.
ALIGN_CENTER
);
// 缩放
image
.
scalePercent
(
60
);
document
.
add
(
image
);
// close
document
.
close
();
return
document
;
}
@Override
public
void
generateTempPDF
(
HttpServletResponse
response
)
throws
Exception
{
PdfReader
reader
=
null
;
PdfStamper
ps
=
null
;
OutputStream
fos
=
null
;
ByteArrayOutputStream
bos
=
null
;
Base64
.
InputStream
fin
=
null
;
ServletOutputStream
out
=
null
;
try
{
// 模板绝对路径--服务器
String
fileName
=
"/template/receipt_template.pdf"
;
// 读取现有模板内容
reader
=
new
PdfReader
(
fileName
);
// 创建输出流
bos
=
new
ByteArrayOutputStream
();
// 实例化PdfStamper准备编辑pdf内容
ps
=
new
PdfStamper
(
reader
,
bos
);
// 获取表单所有元素
AcroFields
fields
=
ps
.
getAcroFields
();
// 设置具体字体格式的编码, 不设置的话中文可能不会显示
BaseFont
bf
=
BaseFont
.
createFont
(
"STSongStd-Light"
,
"UniGB-UCS2-H"
,
BaseFont
.
NOT_EMBEDDED
);
fields
.
addSubstitutionFont
(
bf
);
// 动态添加所需要的数据,key跟模板中对应文本域名称一致
Map
<
String
,
String
>
map
=
new
HashMap
<>();
map
.
put
(
"code"
,
"1234567890fjdksjfdsfdsffdsjfdssssssttttttttttttttt"
);
map
.
put
(
"table_image"
,
"C:/Users/gxk/Pictures/Saved Pictures/nvm.png"
);
// 渲染
fillData
(
fields
,
map
,
ps
);
//必须要调用这个,否则文档不会生成的
ps
.
setFormFlattening
(
true
);
if
(
ps
!=
null
){
ps
.
close
();
}
//生成pdf路径存放的路径
fos
=
response
.
getOutputStream
();
fos
.
write
(
bos
.
toByteArray
());
}
catch
(
Exception
e
){
e
.
printStackTrace
();
}
finally
{
if
(
fos
!=
null
){
fos
.
flush
();
fos
.
close
();
}
if
(
bos
!=
null
){
bos
.
close
();
}
if
(
reader
!=
null
){
reader
.
close
();
}
}
}
/**
* 填充模板中的数据
* @param fields
* @param data 是一个Map<String,String> 主要存储 key 表单模板中的单元格名 value为想要赋的值,遍历
* @param ps
*/
public
void
fillData
(
AcroFields
fields
,
Map
<
String
,
String
>
data
,
PdfStamper
ps
)
{
try
{
for
(
String
key
:
data
.
keySet
())
{
String
value
=
data
.
get
(
key
);
if
(
key
.
contains
(
"image"
))
{
addImageToPdf
(
key
,
fields
,
ps
,
value
);
continue
;
}
// 为字段赋值,注意字段名称是区分大小写的
fields
.
setField
(
key
,
value
);
}
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
}
/**
* 添加图片
* @param key 应为模板名
* @param form 动态字段
* @param stamper
* @param filePath 本地图片路径
* @throws DocumentException
* @throws IOException
* @throws IOException
*/
private
static
void
addImageToPdf
(
String
key
,
AcroFields
form
,
PdfStamper
stamper
,
String
filePath
)
throws
DocumentException
,
IOException
,
IOException
{
// 通过图片域名获取所在页和坐标,左下角为起点
int
pageNo
=
form
.
getFieldPositions
(
key
).
get
(
0
).
page
;
Rectangle
signRect
=
form
.
getFieldPositions
(
key
).
get
(
0
).
position
;
float
x
=
signRect
.
getLeft
();
float
y
=
signRect
.
getBottom
();
// 读图片
Image
image
=
Image
.
getInstance
(
filePath
);
// 获取操作的页面
PdfContentByte
under
=
stamper
.
getOverContent
(
pageNo
);
// 根据域的大小缩放图片
image
.
scaleToFit
(
signRect
.
getWidth
()
*
2
,
signRect
.
getHeight
());
// 添加图片并设置位置(个人通过此设置使得图片垂直水平居中,可参考,具体情况已实际为准)
image
.
setAbsolutePosition
(
x
,
y
);
under
.
addImage
(
image
);
}
}
...
...
quality-review/src/main/java/com/ruoyi/web/BookController.java
View file @
8840ebf2
package
com
.
ruoyi
.
web
;
import
com.itextpdf.text.Document
;
import
com.ruoyi.common.annotation.Anonymous
;
import
com.ruoyi.common.core.controller.BaseController
;
import
com.ruoyi.common.core.domain.R
;
import
com.ruoyi.common.core.page.TableDataInfo
;
...
...
@@ -9,6 +11,7 @@ import com.ruoyi.web.request.BookDeleteRequest;
import
com.ruoyi.web.request.BookListRequest
;
import
io.swagger.annotations.Api
;
import
io.swagger.annotations.ApiOperation
;
import
org.apache.poi.xwpf.usermodel.XWPFDocument
;
import
org.apache.skywalking.apm.toolkit.trace.Tag
;
import
org.apache.skywalking.apm.toolkit.trace.Tags
;
import
org.apache.skywalking.apm.toolkit.trace.Trace
;
...
...
@@ -16,6 +19,8 @@ import org.springframework.beans.factory.annotation.Autowired;
import
org.springframework.validation.annotation.Validated
;
import
org.springframework.web.bind.annotation.*
;
import
javax.servlet.http.HttpServletResponse
;
import
java.io.OutputStream
;
import
java.util.Arrays
;
import
java.util.List
;
...
...
@@ -73,4 +78,17 @@ public class BookController extends BaseController {
return
getDataTable
(
books
);
}
@Anonymous
@ApiOperation
(
"Download"
)
@GetMapping
(
value
=
"/download"
,
produces
=
"application/json"
)
public
void
download
(
HttpServletResponse
response
)
{
response
.
setHeader
(
"content-disposition"
,
"attachment;fileName="
+
"ReceiptPrinter.pdf"
);
try
{
// bookService.generateItextPdfDocument(response.getOutputStream());
bookService
.
generateTempPDF
(
response
);
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
}
}
quality-review/src/main/resources/fonts/STSong.TTF
0 → 100644
View file @
8840ebf2
File added
quality-review/src/main/resources/template/receipt_template.pdf
0 → 100644
View file @
8840ebf2
File added
ruoyi-common/pom.xml
View file @
8840ebf2
...
...
@@ -52,13 +52,13 @@
<groupId>
org.apache.commons
</groupId>
<artifactId>
commons-lang3
</artifactId>
</dependency>
<!-- JSON工具类 -->
<dependency>
<groupId>
com.fasterxml.jackson.core
</groupId>
<artifactId>
jackson-databind
</artifactId>
</dependency>
<!-- 动态数据源 -->
<dependency>
<groupId>
com.baomidou
</groupId>
...
...
@@ -158,6 +158,17 @@
<version>
3.0.3
</version>
</dependency>
<!-- PDF -->
<dependency>
<groupId>
com.itextpdf
</groupId>
<artifactId>
itextpdf
</artifactId>
<version>
5.5.13.3
</version>
</dependency>
<dependency>
<groupId>
com.itextpdf
</groupId>
<artifactId>
itext-asian
</artifactId>
<version>
5.2.0
</version>
</dependency>
</dependencies>
</project>
\ No newline at end of file
</project>
ruoyi-common/src/main/java/com/ruoyi/common/utils/PdfUtils.java
0 → 100644
View file @
8840ebf2
package
com
.
ruoyi
.
common
.
utils
;
import
com.itextpdf.text.*
;
import
com.itextpdf.text.pdf.BaseFont
;
import
com.itextpdf.text.pdf.PdfPCell
;
import
java.io.IOException
;
/**
* PDF工具类
* @author gxk
*/
public
class
PdfUtils
{
/**
* 标题
* @param content
* @return
* @throws IOException
* @throws DocumentException
*/
public
static
Paragraph
createTitle
(
String
content
)
throws
IOException
,
DocumentException
{
Font
font
=
new
Font
(
getBaseFont
(),
24
,
Font
.
BOLD
);
Paragraph
paragraph
=
new
Paragraph
(
content
,
font
);
paragraph
.
setAlignment
(
Element
.
ALIGN_CENTER
);
return
paragraph
;
}
/**
* H1标题
* @param content
* @return
* @throws IOException
* @throws DocumentException
*/
public
static
Paragraph
createChapterH1
(
String
content
)
throws
IOException
,
DocumentException
{
Font
font
=
new
Font
(
getBaseFont
(),
22
,
Font
.
BOLD
);
Paragraph
paragraph
=
new
Paragraph
(
content
,
font
);
paragraph
.
setAlignment
(
Element
.
ALIGN_LEFT
);
return
paragraph
;
}
/**
* H2标题
* @param content
* @return
* @throws IOException
* @throws DocumentException
*/
public
static
Paragraph
createChapterH2
(
String
content
)
throws
IOException
,
DocumentException
{
Font
font
=
new
Font
(
getBaseFont
(),
18
,
Font
.
BOLD
);
Paragraph
paragraph
=
new
Paragraph
(
content
,
font
);
paragraph
.
setAlignment
(
Element
.
ALIGN_LEFT
);
return
paragraph
;
}
/**
* 段
* @param content
* @return
* @throws IOException
* @throws DocumentException
*/
public
static
Paragraph
createParagraph
(
String
content
)
throws
IOException
,
DocumentException
{
Font
font
=
new
Font
(
getBaseFont
(),
12
,
Font
.
NORMAL
);
Paragraph
paragraph
=
new
Paragraph
(
content
,
font
);
paragraph
.
setAlignment
(
Element
.
ALIGN_LEFT
);
// 设置左缩进
paragraph
.
setIndentationLeft
(
12
);
// 设置右缩进
paragraph
.
setIndentationRight
(
12
);
// 设置首行缩进
paragraph
.
setFirstLineIndent
(
24
);
// 行间距
paragraph
.
setLeading
(
20
f
);
// 设置段落上空白
paragraph
.
setSpacingBefore
(
5
f
);
// 设置段落下空白
paragraph
.
setSpacingAfter
(
10
f
);
return
paragraph
;
}
/**
* 表格内容
* @param content
* @return
* @throws IOException
* @throws DocumentException
*/
public
static
PdfPCell
createCell
(
String
content
)
throws
IOException
,
DocumentException
{
PdfPCell
cell
=
new
PdfPCell
();
cell
.
setVerticalAlignment
(
Element
.
ALIGN_MIDDLE
);
cell
.
setHorizontalAlignment
(
Element
.
ALIGN_CENTER
);
Font
font
=
new
Font
(
getBaseFont
(),
12
,
Font
.
NORMAL
);
cell
.
setPhrase
(
new
Phrase
(
content
,
font
));
return
cell
;
}
/**
* 字体
* @return
* @throws IOException
* @throws DocumentException
*/
public
static
BaseFont
getBaseFont
()
throws
IOException
,
DocumentException
{
return
BaseFont
.
createFont
(
"STSong-Light"
,
"UniGB-UCS2-H"
,
BaseFont
.
NOT_EMBEDDED
);
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment