文件下载加水印工具类(pdf、word、excel、图片)

文件加水印实现

支持文件类型

 	/**
     * 目前可支持加水印的文件类型
     */
    private static List<String> FILE_TYPE_WATER_LIST = Arrays.asList(
            ".jpg", ".jpeg", ".png",".bmp",".JPG",".PNG",".JPEG",".BMP", ".docx", ".xlsx", ".pptx", ".doc", ".xls", ".ppt",  ".pdf"
    );

maven 依赖

 	<properties>
		<!-- pdf  -->
        <itext.version>7.0.3</itext.version>
    </properties>
    
    <dependencies>
		<!-- PDF -->
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext7-core</artifactId>
            <version>${itext.version}</version>
            <type>pom</type>
        </dependency>
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>kernel</artifactId>
            <version>${itext.version}</version>
        </dependency>
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>io</artifactId>
            <version>${itext.version}</version>
        </dependency>
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>layout</artifactId>
            <version>${itext.version}</version>
        </dependency>
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>forms</artifactId>
            <version>${itext.version}</version>
        </dependency>
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>pdfa</artifactId>
            <version>${itext.version}</version>
        </dependency>
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>pdftest</artifactId>
            <version>${itext.version}</version>
        </dependency>
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>font-asian</artifactId>
            <version>${itext.version}</version>
        </dependency>
        <!-- word -->
        <dependency>
            <groupId>e-iceblue</groupId>
            <artifactId>spire.doc.free</artifactId>
            <version>2.7.3</version>
        </dependency>
        <!-- excel  -->
        <dependency>
            <groupId>e-iceblue</groupId>
            <artifactId>spire.xls.free</artifactId>
            <version>2.2.0</version>
        </dependency>
        <dependency>
            <groupId>e-iceblue</groupId>
            <artifactId>spire.pdf.free</artifactId>
            <version>2.2.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.15</version>
        </dependency>

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.15</version>
        </dependency>

        <!-- ppt -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>ooxml-schemas</artifactId>
            <version>1.0</version>
            <exclusions>
                <!--解决含嵌入文件ppt转换报错 ArrayStoreException-->
                <exclusion>
                    <artifactId>xmlbeans</artifactId>
                    <groupId>org.apache.xmlbeans</groupId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>com.twelvemonkeys.servlet</groupId>
            <artifactId>servlet</artifactId>
            <version>3.6</version>
        </dependency>

        <!-- 图片 -->
        <!--twelvemonkeys图片处理-->
        <dependency>
            <groupId>com.twelvemonkeys.imageio</groupId>
            <artifactId>imageio-jpeg</artifactId>
            <version>3.6</version>
        </dependency>
        <dependency>
            <groupId>com.twelvemonkeys.imageio</groupId>
            <artifactId>imageio-tiff</artifactId>
            <version>3.6</version>
        </dependency>

    </dependencies>
    
	 <repositories>
	 	<repository>
            <id>com.e-iceblue</id>
            <name>e-iceblue</name>
            <url>http://repo.e-iceblue.com/nexus/content/groups/public/</url>
        </repository>
        
    </repositories>

若无法导入e-iceblue下的包可能是因为mavensetting.xml配置了私服 无法连接至http://repo.e-iceblue.com/nexus/content/groups/public/下载jar包
将私服配置注释一下即可

controller测试

	@GetMapping("/test")
    public void testWaterMark(@RequestParam String watermark,HttpServletResponse response) throws IOException {
        response.setCharacterEncoding(Charsets.UTF_8.name());
        //response.setContentType("application/ppt");  //文件类型设置
        String header = getRequest().getHeader("User-Agent").toUpperCase();
        Boolean flag = header.contains("MSIE") || header.contains("TRIDENT") || header.contains("EDGE");
        if (flag) {
            response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode("Snipaste_2021-09-16_15-18-17.jpg", "UTF-8"));
        } else {
            response.setHeader("Content-Disposition", "attachment; filename=" + new String("Snipaste_2021-09-16_15-18-17.jpg".getBytes("utf-8"), "ISO8859-1"));
        }
        String path = "D:\\cloudpivot\\资料\\Snipaste_2021-09-16_15-18-17.jpg";//原文件绝对路径
        String savePath = "D:/cloudpivot/资料/水印/";//生成水印文件暂存地址  后续删除该文件
        String suffix = path.substring(path.lastIndexOf('.'));
        if (FILE_TYPE_WATER_LIST.contains(suffix)) {
            FileWaterMarkUtils.generateFile(savePath,path, watermark, response,new File(path));
        }else {
            System.out.println("不支持添加水印");
        }
    }

response头部信息统一设置在controller了,工具类中未作设置!

加水印工具类

package com.authine.cloudpivot.ext.util;

import com.itextpdf.io.font.PdfEncodings;
import com.itextpdf.kernel.events.Event;
import com.itextpdf.kernel.events.IEventHandler;
import com.itextpdf.kernel.events.PdfDocumentEvent;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.kernel.pdf.extgstate.PdfExtGState;
import com.itextpdf.layout.Canvas;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.property.TextAlignment;
import com.itextpdf.layout.property.VerticalAlignment;
import com.spire.doc.Document;
import com.spire.doc.FileFormat;
import com.spire.doc.Section;
import com.spire.doc.TextWatermark;
import com.spire.doc.documents.WatermarkLayout;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.sl.usermodel.PictureData;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
import org.apache.poi.xslf.usermodel.XSLFPictureShape;
import org.apache.poi.xslf.usermodel.XSLFSlide;
import org.apache.poi.xssf.usermodel.XSSFRelation;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.core.io.ClassPathResource;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.UUID;


/**
 * @author zhouzhicheng
 * @version 1.0  2021/9/14
 */
@Slf4j
public class FileWaterMarkUtils {
    private static final String PDF = "pdf";
    private static final String DOC = ".doc.docx";
    private static final String XLS = ".xls.xlsx";
    private static final String PPT = ".ppt.pptx";
    private static final String IMG = ".jpg.JPG.png.PNG.jpeg.JPEG.bmp.BMP";

    /**
     * 生成水印文件
     * @param saveFilePath  水印生成文件暂存路径
     * @param fileName      原文件绝对路径
     * @param watermark     水印内容
     * @param response
     */
    public static void generateFile(String saveFilePath,String fileName,String watermark, HttpServletResponse response,File file){
        log.info("添加水印文件:{}",fileName);
        log.info("水印内容:{}",watermark);

        //获取文件后缀
        String suffix = fileName.substring((fileName.lastIndexOf(".") + 1));
        
        if (PDF.equals(suffix)){
            //generatePDF(fileName,watermark,response);
             //多行多条水印
            generatePDF2(saveFilePath,file,watermark,response);
            log.info("生成水印pdf成功!");
        }
        if (DOC.contains(suffix)){
            generateDOC(saveFilePath,fileName,watermark,response);
            log.info("生成水印word成功!");
        }
        if (XLS.contains(suffix)){
            generateExcel(saveFilePath,fileName,watermark,response);
            log.info("生成水印excel成功!");
        }
        if (PPT.contains(suffix)){
            generatePPT(saveFilePath,fileName,watermark,response);
            log.info("生成水印ppt成功!");
        }
        if (IMG.contains(suffix)){
            generateImage(saveFilePath,fileName,watermark,response);
            log.info("生成水印image成功!");
        }

    }
    private static void generateImage(String savePath,String fileName,String watermark,HttpServletResponse response){
        try {
            File fileImage = new File(savePath.concat(new File(fileName).getName()));
            log.info("生成水印后的图片地址:{}",fileImage);
            setImageWatermark(fileName,fileImage,Color.GRAY,watermark);
            outputStream(fileImage,response);
            fileImage.delete();
        }catch (Exception e){
            log.error(e.getMessage(),e);
        }
    }
    private static void generatePPT(String savePath,String fileName,String watermark,HttpServletResponse response){
        try {
            File file = new File(fileName);
            XMLSlideShow slideShow = new XMLSlideShow(new FileInputStream(file));
            ByteArrayOutputStream os = getWaterImage(watermark);
            PictureData pictureData = slideShow.addPicture(os.toByteArray(), PictureData.PictureType.PNG);
            for (XSLFSlide slide : slideShow.getSlides()) {
                XSLFPictureShape pictureShape = slide.createPicture(pictureData);
                pictureShape.setAnchor(pictureShape.getAnchor());
            }
            log.info("水印PPT生成成功:{}",savePath.concat(file.getName()));
            //生成新的文件
            File filePPT = new File(savePath.concat(file.getName()));
            FileOutputStream out = new FileOutputStream(filePPT);
            slideShow.write(out);
            outputStream(filePPT,response);
            filePPT.delete();
            slideShow.close();
        }catch (Exception e){
            log.error(e.getMessage(),e);
        }
    }

    private static void generateExcel(String savePath,String fileName,String watermark,HttpServletResponse response){
        try {
            File file = new File(fileName);
            //读取excel文件
            XSSFWorkbook workbook = new XSSFWorkbook(new FileInputStream(file));
            ByteArrayOutputStream os = getWaterImage(watermark);
            int pictureIdx = workbook.addPicture(os.toByteArray(), Workbook.PICTURE_TYPE_PNG);
            for (int i = 0; i < workbook.getNumberOfSheets(); i++) {//获取每个Sheet表
                XSSFSheet sheet = workbook.getSheetAt(i);
                String rID = sheet.addRelation(null, XSSFRelation.IMAGES, workbook.getAllPictures().get(pictureIdx)).getRelationship().getId();
                sheet.getCTWorksheet().addNewPicture().setId(rID);
            }
            log.info("水印excel生成成功:{}",savePath.concat(file.getName()));
            // Excel文件生成后存储的位置
            File fileExcel = new File(savePath.concat(file.getName()));
            OutputStream fos = new FileOutputStream(fileExcel);
            workbook.write(fos);
            outputStream(fileExcel,response);
            fileExcel.delete();
            workbook.close();
        }catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }

    private static void generateDOC(String savePath,String fileName,String watermark,HttpServletResponse response){

        File file = new File(fileName);
        Document document = new Document();
        document.loadFromFile(file.toString());
        //添加水印
        //InsertTextWatermark(document.getSections().get(0), watermark);
        InsertManyTextWatermark(document,watermark);
        log.info("水印doc生成成功:{}",savePath.concat(file.getName()));
        String suffix = fileName.substring(fileName.lastIndexOf('.'));
        //存储生成水印的文件
        document.saveToFile(savePath.concat(file.getName()), suffix.equals("doc")? FileFormat.Doc: FileFormat.Docx);
        File fileS = new File(savePath, file.getName());
        //写出文件
        outputStream(fileS,response);
        fileS.delete();
        document.close();
    }

    private static void generatePDF(String fileName,String watermark,HttpServletResponse response){
        try {
            File file = new File(fileName);
            FileInputStream fis = new FileInputStream(file);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            PdfReader readerInfo = new PdfReader(fis);
            PdfDocument docInfo = new PdfDocument(readerInfo, new PdfWriter(baos));
            //中文字体
            File tempFile = File.createTempFile(UUID.randomUUID().toString().replaceAll("-", ""), ".otf");
            InputStream input = new ClassPathResource("NotoSerifCJKsc.otf").getInputStream();
            Files.copy(input, tempFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
            String fontPath = tempFile.getAbsolutePath();
            //加水印
            addWater(docInfo, fontPath,watermark);
            //关闭文档
            docInfo.close();
            readerInfo.close();
            ServletOutputStream fos = response.getOutputStream();
            fos.write(baos.toByteArray());
            fos.flush();
            fos.close();
            baos.close();
            fis.close();
        } catch (Exception e) {
           log.error(e.getMessage(), e);
        }
    }
    /**
     * 图片添加水印
     *
     * @param srcImgPath       需要添加水印的图片的路径
     * @param fileImage       添加水印后图片
     * @param markContentColor 水印文字的颜色
     * @param waterMarkContent 水印的文字
     */
    private static void setImageWatermark(String srcImgPath, File fileImage, Color markContentColor, String waterMarkContent) {
        FileOutputStream outImgStream = null;
        String suffix = srcImgPath.substring(srcImgPath.lastIndexOf('.')+1);
        try {
            // 读取原图片信息
            File srcImgFile = new File(srcImgPath);
            Image srcImg = ImageIO.read(srcImgFile);
            int srcImgWidth = srcImg.getWidth(null);
            int srcImgHeight = srcImg.getHeight(null);
            // 加水印
            BufferedImage bufImg = new BufferedImage(srcImgWidth, srcImgHeight, BufferedImage.TYPE_INT_RGB);
            Graphics2D g = bufImg.createGraphics();
            g.drawImage(srcImg, 0, 0, srcImgWidth, srcImgHeight, null);
            Font font = new Font("宋体", Font.BOLD, srcImgHeight / 6);
            //根据图片的背景设置水印颜色
            g.setColor(markContentColor);
            //设置旋转角度
            g.rotate(Math.toRadians(-45), (double) bufImg.getWidth() / 2, (double) bufImg.getHeight() / 2);
            //设置水印透明度
            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.2F));

            g.setFont(font);
            int x = (srcImgWidth - getWatermarkLength(waterMarkContent, g)) / 2;
            int y = srcImgHeight / 2;
            g.drawString(waterMarkContent, x, y);
            g.dispose();
            // 输出图片
            outImgStream = new FileOutputStream(fileImage);
            ImageIO.write(bufImg, suffix, outImgStream);
            outImgStream.flush();
            outImgStream.close();
        } catch (Exception e) {
            log.error(e.getMessage(),e);
        } finally {
            if (outImgStream != null) {
                try {
                    outImgStream.close();
                } catch (IOException e) {
                    log.error(e.getMessage(),e);
                }
            }
        }
    }
    /**
     * 文件写出流
     * @param file
     * @param response
     */
    private static void outputStream(File file, HttpServletResponse response){
        try {
            FileInputStream fis = new FileInputStream(file);
            BufferedInputStream bis = new BufferedInputStream(fis);
            BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream());
            byte[] buf = new byte[4096];
            int length = bis.read(buf);
            //保存文件
            while(length != -1)
            {
                bos.write(buf, 0, length);
                length = bis.read(buf);
            }
            bos.flush();
            bos.close();
            bis.close();
        }catch (Exception e){
            log.error(e.getMessage(),e);
        }

    }

    /**
     * 获取水印文字总长度
     *
     * @param waterMarkContent 水印的文字
     * @param g
     * @return 水印文字总长度
     */
    private static int getWatermarkLength(String waterMarkContent, Graphics2D g) {
        return g.getFontMetrics(g.getFont()).charsWidth(waterMarkContent.toCharArray(), 0, waterMarkContent.length());
    }
    /**
     * 获取水印文字图片流
     *
     * @param text
     * @return
     */
    private static ByteArrayOutputStream getWaterImage(String text) {
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        try {
            // 导出到字节流B
            BufferedImage image = createWaterMarkImageBig(text);
            ImageIO.write(image, "png", os);
        } catch (IOException e) {
           log.info(e.getMessage(),e);
        }
        return os;
    }
    /**
     * 根据文字生成水印图片(大号 平铺)
     *
     * @param text
     * @return
     */
    private static BufferedImage createWaterMarkImageBig(String text) {
        Integer width = 1000;
        Integer height = 800;
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);// 获取bufferedImage对象
        Font font = new Font("宋体", Font.PLAIN, 70);
        Graphics2D g2d = image.createGraphics();
        image = g2d.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT);
        g2d.dispose();
        g2d = image.createGraphics();
        //设置字体颜色和透明度
        g2d.setColor(new Color(0, 0, 0, 60));
        //设置字体
        g2d.setStroke(new BasicStroke(1));
        //设置字体类型  加粗 大小
        g2d.setFont(font);
        //设置倾斜度
        g2d.rotate(Math.toRadians(-30), (double) image.getWidth() / 2, (double) image.getHeight() / 2);
        FontRenderContext context = g2d.getFontRenderContext();
        Rectangle2D bounds = font.getStringBounds(text, context);
        double x = (width - bounds.getWidth()) / 2;
        double y = (height - bounds.getHeight()) / 2;
        double ascent = -bounds.getY();
        double baseY = y + ascent;
        //写入水印文字原定高度过小,所以累计写水印,增加高度
        g2d.drawString(text, (int) x, (int) baseY);
        //设置透明度
        g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
        //释放对象
        g2d.dispose();
        return image;
    }

    /**
     * 自定义方法插入文本水印并格式水印效果
     * word
     */
    private static void InsertTextWatermark(Section section,String watermark){
        TextWatermark txtWatermark = new TextWatermark();
        txtWatermark.setText(watermark);
        txtWatermark.setFontSize(40);
        txtWatermark.setColor(Color.LIGHT_GRAY);
        txtWatermark.setLayout(WatermarkLayout.Diagonal);
        section.getDocument().setWatermark(txtWatermark);
    }
    /**
     * word 通过页眉生成多条文字水印
     * @param document
     * @param watermark
     */
    private static void InsertManyTextWatermark(Document document,String watermark){
        ShapeObject shape = new ShapeObject(document, ShapeType.Text_Plain_Text);
        shape.setWidth(50);
        shape.setHeight(15);
        //设置艺术字文本内容、位置及样式
        shape.setVerticalPosition(10);
        shape.setHorizontalPosition(5);
        shape.setRotation(330);
        shape.getWordArt().setText(watermark);

        shape.setFillColor(Color.GRAY);
        shape.setLineStyle(ShapeLineStyle.Single);
        shape.setStrokeColor(new Color(192, 192, 192, 255));
        shape.setStrokeWeight(1);

        Section section = document.getSections().get(0);
        //获取section的页眉
        HeaderFooter header = section.getHeadersFooters().getHeader();
        com.spire.doc.documents.Paragraph paragraph;
        for (int i = 0; i < 3; i++) {
            //添加段落到页眉
            paragraph = header.addParagraph();
            for (int j = 0; j < 3; j++) {
                //复制艺术字并设置多行多列位置
                shape = (ShapeObject) shape.deepClone();
                shape.setVerticalPosition(150 + 180 * i);
                shape.setHorizontalPosition(40 + 150 * j);
                paragraph.getChildObjects().add(shape);
            }
        }
    }
    /**
     * PDF
     * @param docInfo
     */
    private static void addWater(PdfDocument docInfo,String path,String watermark){
        docInfo.addEventHandler(PdfDocumentEvent.END_PAGE, new IEventHandler() {
            @Override
            public void handleEvent(Event event) {
                PdfDocumentEvent docEvent = (PdfDocumentEvent) event;
                PdfDocument pdfDoc = docEvent.getDocument();
                PdfPage page = docEvent.getPage();
                PdfFont font = null;
                try {
                    font = PdfFontFactory.createFont(path, PdfEncodings.IDENTITY_H, false);

                } catch (IOException e) {
                    log.error(e.getMessage(),e);
                }
                PdfCanvas canvas = new PdfCanvas(page);
                PdfExtGState gs1 = new PdfExtGState();
                gs1.setFillOpacity(0.10f); // 水印透明度
                canvas.setExtGState(gs1);
                new Canvas(canvas, pdfDoc, page.getPageSize()).setFontSize(60)
                        .setFont(font).showTextAligned(new Paragraph(watermark), 298, 421,
                        pdfDoc.getPageNumber(page), TextAlignment.CENTER, VerticalAlignment.MIDDLE, 45);
            }
        });
    }
    /**
     *  PDF多行多条水印
     */
    static void generatePDF2(String savePath,File file,String watermark,HttpServletResponse response){
        //创建PdfDocument类的对象
        com.spire.pdf.PdfDocument pdf = new com.spire.pdf.PdfDocument();
        //加载测试文档
        pdf.loadFromFile(file.toString());
        //添加一个空白页,目的为了删除jar包添加的水印,后面再移除这一页
        pdf.getPages().add();
        //获取测试文档中的第一页
        //遍历文档中的页
        for (int i = 0; i < pdf.getPages().getCount(); i++) {
            PdfPageBase page = pdf.getPages().get(i);
            //添加文本水印
            addPDFWatermark(page, watermark);
        }
        //移除第一个页
        pdf.getPages().remove(pdf.getPages().get(pdf.getPages().getCount()-1));
        //保存文档
        pdf.saveToFile(savePath.concat(file.getName()));
        File fileS = new File(savePath, file.getName());
        //写出文件
        outputStream(fileS,response);
        fileS.delete();
        pdf.close();
    }
    static void addPDFWatermark(PdfPageBase page, String watermark) {
        Dimension2D dimension2D = new Dimension();
        //水印数量
        dimension2D.setSize(page.getCanvas().getClientSize().getWidth() / 5, page.getCanvas().getClientSize().getHeight() / 5);
        PdfTilingBrush brush = new PdfTilingBrush(dimension2D);
        //透明度
        brush.getGraphics().setTransparency(0.4F);
        brush.getGraphics().save();
        //浮动
        brush.getGraphics().translateTransform((float) brush.getSize().getWidth() / 5, (float) brush.getSize().getHeight() / 5);
        //倾斜度(负:上倾斜,正:下倾斜)
        brush.getGraphics().rotateTransform(-45);
        //设置字体颜色
        PdfBrush brush_color = new PdfSolidBrush(new PdfRGBColor(Color.GRAY));
        //水印内容和水印坐标
        brush.getGraphics().drawString(watermark, new PdfTrueTypeFont(new Font("宋体", Font.PLAIN,15),true), brush_color, 25, 30 , new PdfStringFormat(PdfTextAlignment.Center));
        brush.getGraphics().restore();
        brush.getGraphics().setTransparency(1);
        Rectangle2D loRect = new Rectangle2D.Float();
        loRect.setFrame(new Point2D.Float(0, 0), page.getCanvas().getClientSize());
        page.getCanvas().drawRectangle(brush, loRect);
    }
}

生成多行多条水印pdf时linux环境水印中文字体不显示或乱码处理:

fc-list :lang=zh 检查linux服务器中文字体
在这里插入图片描述若没有中文字体则执行以下操作

将windows的字体复制下来 路径:C:\Windows\Fonts
丢到linux服务器上 路径:/usr/share/fonts 可以自建一个文件夹放复制过来的字体文件
在这里插入图片描述
winfont为自建文件夹 字体则是windows里的一些中文字体包(微软雅黑、宋体)
再刷新一下linux的字体缓存 fc-cache -fv命令
最后重启自己的web应用程序即可!

resources 两个字体附件(生成单条水印pdf时需要)
在这里插入图片描述
链接:https://pan.baidu.com/s/1uLIbRpx4K8SXkxWxViFCeA
提取码:42l5

水印内容不传便可下载不加水印文件!!

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值