java实现预览服务器文件,不进行下载,并增加水印效果

通过文件路径获取文件,对不同类型的文件进行不同处理,将Word文件转成pdf文件预览,并早呢更加水印,暂不支持Excel文件,如果浏览器不支持PDF文件预览需要下载插件。文中currentUser.getUserid(),即为增加的水印内容,需要替换掉,字符串类型的。

加水印用的包是pdfbox,不是itext7,这两个包有的方法名一致,但是穿的参数类型不一致,引用的包不对,会报错。BufferedImage引用的是java.awt.image.BufferedImage引用成pdfbox的也会报错,有报错的参数注意一下引用的包。

java 复制代码
<dependency>
    <groupId>org.apache.pdfbox</groupId>
    <artifactId>pdfbox</artifactId>
    <version>2.0.24</version>
</dependency>
java 复制代码
@RequestMapping("previewFile")
	public void download(String src,HttpServletRequest request,HttpServletResponse response) throws Exception {
		
		String filePath = src;
		System.out.println("filePath:" + filePath);
		File f = new File(filePath);
		if (!f.exists()) {
			response.sendError(404, "File not found!");
			return;
		}
		String fileName = f.getName();
		String extension = getFileExtension(f.getName());

		BufferedInputStream br = new BufferedInputStream(new FileInputStream(f));

		byte[] bs = new byte[1024];
		int len = 0;
		response.reset(); // 非常重要
		URL u = new URL("file:///" + filePath);
		//String contentType = u.openConnection().getContentType();
		String contentType = "";

		if(extension.equals("pdf")){
			contentType = "application/pdf";
			br = addWatermarkToPdf(filePath, currentUser.getUserid());
		}else if (extension.equals("txt")){
			contentType = "text/plain";
		}else if (extension.equals("doc") || extension.equals("docx")){
			contentType = "application/pdf";
			try {
				br = convertToPdf(filePath,currentUser.getUserid());
			}catch (Exception e){
			}
		}else if (extension.equals("jpg") || extension.equals("jpeg")){
			contentType = "image/jpeg";
			br = createWatermarkedImage(filePath, currentUser.getUserid());
		}else if (extension.equals("png")){
			contentType = "image/png";
			br = createWatermarkedImage(filePath, currentUser.getUserid());
		}else if (extension.equals("gif")){
			contentType = "image/gif";
			br = createWatermarkedImage(filePath, currentUser.getUserid());
		}
		//Document docsss = new Document(filePath);


		response.setContentType(contentType+"; charset=UTF-8");
		response.setHeader("Content-Disposition", "inline;filename="
				+ fileName);
		// 文件名应该编码成utf-8,注意:使用时,我们可忽略这句
		OutputStream out = response.getOutputStream();
		while ((len = br.read(bs)) > 0) {
			out.write(bs, 0, len);
		}
		out.flush();
		out.close();
		br.close();
	}


	public static BufferedInputStream createWatermarkedImage(String imagePath, String watermarkText) throws IOException {

		// 读取原始图片
		File file = new File(imagePath);
		BufferedImage targetImg = ImageIO.read(new FileInputStream(file));
		int height = targetImg.getHeight();
		int width = targetImg.getWidth();

		//-------------------------文字水印 start----------------------------
		BufferedImage waterMarkImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
		// 创建画笔
		Graphics2D graphics2D = waterMarkImage.createGraphics();
		// 绘制原始图片
		graphics2D.drawImage(targetImg, 0, 0, width, height, null);

		// 设置水印颜色
		graphics2D.setColor(new Color(255, 255, 255, 255));

		double scale = 1.0;
		if(width < height){
			scale = (double) width / height;
		}
		int fontSize = (int) Math.ceil((double) (height / 25) * scale);
		// 设置字体 画笔字体样式为微软雅黑,加粗,文字大小按比例给
		graphics2D.setFont(new Font("微软雅黑", Font.BOLD, fontSize));

		float alpha = 0.7f; // 设置透明度为50%
		AlphaComposite composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha);
		graphics2D.setComposite(composite);

		// 水印旋转度
		graphics2D.rotate(Math.toRadians(-25), (double) width / 2, (double) height / 2);

		int x = -width * 3;
		int y;
		// 计算水印文字的宽度
		FontMetrics fontMetrics = graphics2D.getFontMetrics();
		int watermarkWidth = fontMetrics.stringWidth(watermarkText);
		// 水印横向间隔
		int positionWidth = (int)(width * 0.12);
		// 水印竖向间隔
		int positionHeight  = (int)(height * 0.12);

		while (x < width * 3) {
			y = -height * 3;
			while (y < height * 3) {
				graphics2D.drawString(watermarkText, x, y);
				y += fontSize + positionWidth;
			}
			x += watermarkWidth + positionHeight;
		}

		graphics2D.dispose();
		ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
		ImageIO.write(waterMarkImage, "png", outputStream);
		byte[] imageBytes = outputStream.toByteArray();

		return new BufferedInputStream(new ByteArrayInputStream(imageBytes));
	}

	public static BufferedInputStream addWatermarkToPdf(String filePath,String userId) throws IOException {
		// 加载PDF文档
		PDDocument document = PDDocument.load(new File(filePath));
		try {
			// 遍历所有页面
			for (PDPage page : document.getPages()) {

				// 获取页面的媒体框(即页面的大小)
				PDRectangle mediaBox = page.getMediaBox();
				float pageWidth = mediaBox.getWidth();
				float pageHeight = mediaBox.getHeight();
				// 创建内容流,使用APPEND模式
				PDPageContentStream contentStream = new PDPageContentStream(document, page, PDPageContentStream.AppendMode.APPEND, true, true);
				// 设置水印字体和大小
				contentStream.setFont(PDType1Font.HELVETICA_BOLD, 36);
				// 设置水印颜色(RGB)
				contentStream.setNonStrokingColor(200, 200, 200);

				// 设置文本水印的参数
				String watermarkText = userId;
				PDType1Font font = PDType1Font.HELVETICA_BOLD;
				float fontSize = 20;
				float textWidth = font.getStringWidth(watermarkText) / 1000 * fontSize;
				float textHeight = fontSize;
				float xStep = pageWidth / 4; // 文本在x轴上的重复间隔
				float yStep = pageHeight / 12; // 文本在y轴上的重复间隔,可以根据需要调整

				// 绘制文本水印
				for (float y = 0; y < pageHeight; y += yStep) {
					for (float x = 0; x < pageWidth; x += xStep) {
						// 设置文本颜色(RGB),这里使用白色以确保在红色背景上可见
						contentStream.setStrokingColor(255, 255, 255);

						// 设置字体和大小
						contentStream.beginText();
						contentStream.setFont(font, fontSize);
						contentStream.newLineAtOffset(x, y);

						// 设置文本旋转
						//contentStream.newLineAtOffset(xx, yy);
						//contentStream.setTextMatrix(0, -0.5f, 0.5f, 0, 0, 0);
						contentStream.setTextMatrix(0.5f, 0.5f, -0.5f, 0.5f, x, y);
						contentStream.showText(watermarkText);
						contentStream.endText();
					}
				}
				// 关闭内容流
				contentStream.close();
			}
			ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
			document.save(outputStream);
			document.close();
			return new BufferedInputStream(new ByteArrayInputStream(outputStream.toByteArray()));
			// 保存并关闭PDF文档
			//document.save(new File("watermarked.pdf"));
			//document.close();
		} finally {
			if (document != null) {
				document.close();
			}
		}
	}

	public static String getFileExtension(String fileName) {
		if (fileName == null || fileName.isEmpty()) {
			return "";
		}
		int dotIndex = fileName.lastIndexOf('.');
		if (dotIndex == -1 || dotIndex == fileName.length() - 1) {
			// No dot found or dot is at the end (e.g., "file.")
			return "";
		}
		return fileName.substring(dotIndex + 1);
	}
	public static BufferedInputStream convertToPdf(String wordFilePath,String userId) throws Exception {
		// 加载Word文档
		Document doc = new Document(wordFilePath);
		// 创建一个字节数组输出流来保存PDF内容
		ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
		// 设置PDF保存选项(可选,这里使用默认设置)
		PdfSaveOptions saveOptions = new PdfSaveOptions();
		// 将文档保存为PDF格式到字节数组输出流中
		doc.save(byteArrayOutputStream, saveOptions);

		if (byteArrayOutputStream.size() == 0) {
			throw new IllegalArgumentException("ByteArrayOutputStream is empty");
		}

		// 将ByteArrayOutputStream的内容转换为ByteArrayInputStream
		ByteArrayInputStream bais = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());

		// 使用PDDocument.load方法将流转换为PDDocument对象
		PDDocument pdDocument = PDDocument.load(bais);
		// 关闭ByteArrayInputStream
		bais.close();


		// 将字节数组转换为字节输入流
		ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
		// 返回BufferedInputStream
		return addWatermarkToWord(pdDocument,userId);
	}

	public static BufferedInputStream addWatermarkToWord(PDDocument document,String userId) throws IOException {
		// 加载PDF文档
		//PDDocument document = PDDocument.load(new File(filePath));
		try {
			// 遍历所有页面
			for (PDPage page : document.getPages()) {

				// 获取页面的媒体框(即页面的大小)
				PDRectangle mediaBox = page.getMediaBox();
				float pageWidth = mediaBox.getWidth();
				float pageHeight = mediaBox.getHeight();
				// 创建内容流,使用APPEND模式
				PDPageContentStream contentStream = new PDPageContentStream(document, page, PDPageContentStream.AppendMode.APPEND, true, true);
				// 设置水印字体和大小
				contentStream.setFont(PDType1Font.HELVETICA_BOLD, 36);
				// 设置水印颜色(RGB)
				contentStream.setNonStrokingColor(200, 200, 200);

				// 设置文本水印的参数
				String watermarkText = userId;
				PDType1Font font = PDType1Font.HELVETICA_BOLD;
				float fontSize = 20;
				float textWidth = font.getStringWidth(watermarkText) / 1000 * fontSize;
				float textHeight = fontSize;
				float xStep = pageWidth / 4; // 文本在x轴上的重复间隔
				float yStep = pageHeight / 12; // 文本在y轴上的重复间隔,可以根据需要调整

				// 绘制文本水印
				for (float y = 0; y < pageHeight; y += yStep) {
					for (float x = 0; x < pageWidth; x += xStep) {
						// 设置文本颜色(RGB),这里使用白色以确保在红色背景上可见
						contentStream.setStrokingColor(255, 255, 255);

						// 设置字体和大小
						contentStream.beginText();
						contentStream.setFont(font, fontSize);
						contentStream.newLineAtOffset(x, y);

						// 设置文本旋转
						//contentStream.newLineAtOffset(xx, yy);
						//contentStream.setTextMatrix(0, -0.5f, 0.5f, 0, 0, 0);
						contentStream.setTextMatrix(0.5f, 0.5f, -0.5f, 0.5f, x, y);
						contentStream.showText(watermarkText);
						contentStream.endText();
					}
				}
				// 关闭内容流
				contentStream.close();
			}
			ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
			document.save(outputStream);
			document.close();
			return new BufferedInputStream(new ByteArrayInputStream(outputStream.toByteArray()));
			// 保存并关闭PDF文档
			//document.save(new File("watermarked.pdf"));
			//document.close();
		} finally {
			if (document != null) {
				document.close();
			}
		}
	}
相关推荐
禁默1 小时前
深入浅出:Java 抽象类与接口
java·开发语言
小万编程2 小时前
【2025最新计算机毕业设计】基于SSM的医院挂号住院系统(高质量源码,提供文档,免费部署到本地)【提供源码+答辩PPT+文档+项目部署】
java·spring boot·毕业设计·计算机毕业设计·项目源码·毕设源码·java毕业设计
白宇横流学长2 小时前
基于Java的银行排号系统的设计与实现【源码+文档+部署讲解】
java·开发语言·数据库
123yhy传奇2 小时前
【学习总结|DAY027】JAVA操作数据库
java·数据库·spring boot·学习·mybatis
想要打 Acm 的小周同学呀2 小时前
亚信科技Java后端外包一面
java·求职·java后端
lishiming03086 小时前
TestEngine with ID ‘junit-jupiter‘ failed to discover tests 解决方法
java·junit·intellij-idea
HEU_firejef6 小时前
设计模式——工厂模式
java·开发语言·设计模式
Kobebryant-Manba6 小时前
单元测试学习2.0+修改私有属性
java·单元测试·log4j
fajianchen6 小时前
应用架构模式
java·开发语言
Code成立6 小时前
《Java核心技术 卷II》流的创建
java·开发语言·流编程