VUE:SpringBoot + Vue 尝鲜,PDF转换例子

博主分享了如何在众多收费的PDF转换软件中,通过开源代码自建一个免费的PDF转图片工具。文章详细展示了前端使用Vue.js实现文件上传和转换触发,后端利用IcePDF库进行转换,并提供了压缩下载的功能。此外,还讨论了市场上诱导付费的现象。
摘要由CSDN通过智能技术生成

最近收到很多文件,为了保持格式统一,需要统一保存为PDF,但是现在在网上搜索下PDF相关的转换软件,号称免费的给你转前几页(日常简单任务已经可以胜任了,可以先pdf拆分后在转换),要不就是收费的,要不号称免费但进去后还是收费的,还有转换是免费的,下载是收费的。

请添加图片描述
上图说什么我也不知道的,动图没有文字。

不过大多数提供的功能还是比较完善的,知识付费时代提供服务收取一定费用无可厚非,但是诱导付费行为不值得提倡,前段时间听说有个公司提供VS Code下载还要收费的,这是真的么。

说这么多呢,其实就是一个原因 我想(bai) (piao),怎么实现这个愿望呢,那么自己尝试实现一个吧。下面以PDF转图片举例看下实现过程,PDF转换在网上有很多开源代码,大家可以尝试下

本人CSS小白,不会修改样式,大家将就看看就可以哈

PDF转图片页面
在这里插入图片描述
转换后直接生成target压缩包下载

在这里插入图片描述

前端实现
<template>
	<el-card>
		<el-row :gutter="10">
			<el-col :span="12">
				<h4 class="mgb20">PDF转图片</h4>
			</el-col>
			<el-col :span="12" align="right">
				<el-button @click=""><i class="icon-heart" style="margin-right: 5px;"></i> <span>点赞</span>
					(<span>12345</span>)</el-button>
			</el-col>
		</el-row>
		<el-row :gutter="10">
			<el-col :span="24">
				<el-card class="mgb20">
					<el-upload ref="upload" class="upload-demo" drag action="#" :auto-upload="false" :limit="1" :before-upload="beforeUpload"
						:http-request="uploadFile">
						<i class="el-icon-upload"></i>
						<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
						<div class="el-upload__tip" slot="tip">只能上传PDF文件,且不超过500kb</div>
					</el-upload>
				</el-card>
			</el-col>
		</el-row>
		<el-row>
			<el-col>
				<el-button type="success" @click="submitUpload">转换</el-button>
			</el-col>
		</el-row>
	</el-card>
</template>

<script>
	import axios from 'axios';
	let server = axios.create({
		transformRequest: [
			function(data) {
				let ret = ''
				for (let it in data) {
					ret += encodeURIComponent(it) + '=' + encodeURIComponent(data[it]) + '&'
				}
				ret = ret.substring(0, ret.lastIndexOf('&'));
				return ret
			}
		],
		headers: {
			'Content-Type': 'application/x-www-form-urlencoded'
		}
	});
	export default {
		data() {
			return {
				user: JSON.parse(localStorage.getItem('wr_user')),
				fileList: [],
				thumbs: ''
			}
		},
		created() {
	
		},
		methods: {	
			//校验格式
			beforeUpload(file) {
				const isPDF = file.type === 'application/pdf';
				if(!isPDF) {
					this.$message.warning('只支持PDF格式文件');
					return false;
				}
			},

			uploadFile(file) {
				const loading = this.$loading({
				    lock: true,
				    text: '转换中,请等待',
				    spinner: 'el-icon-loading',
				    background: 'rgba(0, 0, 0, 0.7)'
				});
				// 把文件放入 FormData 进行提交
				const param = new FormData()
				if (undefined !== file) {
					param.append('files', file.file)
				}
				param.append("username", this.user.username)

				axios({
					url: "/pdf/tools/pdf2img",
					method: "post",
					responseType: 'blob', //不可省,非常重要
					data: param
				}).then((res) => {
					if(res.data.type === 'text/xml') {
						let fileName = window.decodeURI(res.headers['content-disposition'].split('=')[1]);
						let contentType = res.headers['content-type'];
						let blob = new Blob([res.data], {
							type: contentType + ';charset=utf-8'
						});
						let downloadElement = document.createElement('a');
						let href = window.URL.createObjectURL(blob); //创建下载的链接
						downloadElement.href = href;
						downloadElement.download = fileName; //下载后文件名
						document.body.appendChild(downloadElement);
						downloadElement.click(); //点击下载
						document.body.removeChild(downloadElement); //下载完成移除元素
						window.URL.revokeObjectURL(href); //释放掉blob对象
						
						this.$refs.upload.clearFiles();
						if (res.status == 200) {
							this.$message.warning("执行成功");
						} else {
							this.$message.warning("执行失败");
						}
					} else {
						this.$message.warning("请求过于频繁,请稍后再试");
					}
					
					loading.close();
				})
			},

			submitUpload() {
				this.$refs.upload.submit();
			},
		}

	}
</script>

<style>
</style>

后端实现

1、添加maven依赖

<dependency>
    <groupId>org.icepdf.os</groupId>
    <artifactId>icepdf-core</artifactId>
    <version>6.1.2</version>
    <exclusions>
        <exclusion>
            <groupId>javax.media</groupId>
            <artifactId>jai-core</artifactId>
        </exclusion>
    </exclusions>
</dependency>

2、java pdf转img实现

/**
 * 将pdf文件转换为图片
 *
 * @param pdfPath           pdf文件路径
 * @param imagePath         文件存储路径
 * @param imageNamePrefix   保存图片名称前缀
 * @param imageType         保存图片类型
 * @param scale             图片缩放
 * @param rotation          图片旋转
 * @throws IOException
 * @throws PDFException
 * @throws PDFSecurityException
 */

public static List<String> pdf2img(String pdfPath, String imagePath, String imageNamePrefix, String imageType, float scale, float rotation) throws IOException, PDFException, PDFSecurityException {
    List<String> imageList = new ArrayList<>();
    Document document = new Document();
    document.setFile(pdfPath);

    for (int i = 0; i < document.getNumberOfPages(); i++) {
        BufferedImage image = (BufferedImage)document.getPageImage(i, GraphicsRenderingHints.SCREEN, Page.BOUNDARY_CROPBOX, rotation, scale);
        RenderedImage rendImage = image;
        try {
            if("".equals(imageNamePrefix) || null == imageNamePrefix) {
                imageNamePrefix = new File(pdfPath).getName();
            }
            String imgName = imageNamePrefix + "_" + new DecimalFormat("000").format(i) + "." + imageType;
            String savePath = "";
            if("/".equals(imagePath.substring(imagePath.length()-1))) {
                savePath = imagePath + imgName;
            } else {
                savePath = imagePath + "/" + imgName;
            }
            File file = new File(savePath);
            File fileParent = file.getParentFile();
            if (!fileParent.exists()) {
                fileParent.mkdirs();
            }
            if (!file.exists()) {
                file.createNewFile();
            }
            ImageIO.write(rendImage, imageType, file);
            // 保存文件路径
            imageList.add(savePath);
        } catch (IOException e) {
            e.printStackTrace();
        }
        image.flush();
    }
    document.dispose();
    System.out.println("转换完成");
    return imageList;
}

3、controller层

@RequestMapping("/pdf2img")
@ResponseBody
public void pdf2img(@RequestParam("files") MultipartFile[] files,
                       @RequestParam("username") String username,
                       HttpServletResponse response) throws IOException, PDFException, PDFSecurityException {
    List<String> result = new ArrayList<>();
    // 注意:rootPath, pdfPath, imagePath 文件路径修改为自己需要的文件路径
    String rootPath = getPath(FileType.TYPE.ROOT.getCode(), username);
    String pdfPath = getPath(FileType.TYPE.PDF.getCode(), username);
    String imagePath = getPath(FileType.TYPE.IMG.getCode(), username);
    for (MultipartFile file : files) {
        String filename = file.getOriginalFilename();
        FileUtils.createFile(file, pdfPath, filename);
        result = PDFUtils.pdf2img(pdfPath + filename, imagePath, "target", "jpg", 2.5f, 0f);
    }

    // 打包文件
    String zipPath = imagePath + "target.zip";
    FileOutputStream fos = new FileOutputStream(zipPath);
    List<File> fileList = new ArrayList<>();
    for (String path : result) {
        fileList.add(new File(path));
    }
    ZipUtils.toZip(fileList, fos);

    String fileName = zipPath.substring(zipPath.lastIndexOf("/") + 1);
    response.reset();
    response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));

    //读取指定路径下面的文件
    InputStream in = new FileInputStream(zipPath);

    OutputStream outputStream = new BufferedOutputStream(response.getOutputStream());
    response(in, outputStream);
}

4、压缩工具

 /**
 * 文件列表压缩成ZIP
 *
 * @param srcFiles 需要压缩的文件列表
 * @param out      压缩文件输出流
 * @throws RuntimeException 压缩失败会抛出运行时异常
 */
public static void toZip(List<File> srcFiles, OutputStream out) throws RuntimeException {
    long start = System.currentTimeMillis();
    ZipOutputStream zos = null;
    try {
        zos = new ZipOutputStream(out);
        for (File srcFile : srcFiles) {
            byte[] buf = new byte[1024];
            zos.putNextEntry(new ZipEntry(srcFile.getName()));
            int len;
            FileInputStream in = new FileInputStream(srcFile);
            while ((len = in.read(buf)) != -1) {
                zos.write(buf, 0, len);
            }
            zos.closeEntry();
            in.close();
        }
        long end = System.currentTimeMillis();
        System.out.println("压缩完成,耗时:" + (end - start) + " ms");
    } catch (Exception e) {
        throw new RuntimeException("zip error from ZipUtils", e);
    } finally {
        if (zos != null) {
            try {
                zos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
Vue.js 是一个行的前端 JavaScript 框架,主要用于构建用户界面。如果你想在 Vue 应用程序中在线预览 Word 文档,并配备导航栏,可以考虑使用一些库如 jsdocx、pdfobject 或者 Office Online API 来加载和显示文档内容,同时利用 Vue 的组件化特性设计一个导航结构。 jsdocx 可以帮助解析 Word 文档,将其转换为 HTML 以便于展示。PDFObject 可以嵌入 PDF 文件,对于 Word 文档也可以通过转换得到类似效果。Office Online API 则允许直接与 Microsoft Office 服务交互,但可能需要在服务器端处理,然后提供一个安全的链接给客户端预览。 在 Vue 中,你可以创建一个父组件作为容器,包含导航栏,然后嵌套一个子组件用于加载和渲染文档。例如: ```html <template> <div> <nav> <!-- 导航栏 --> <router-link to="/document">Word Document</router-link> </nav> <div v-if="showDocument"> <word-preview :doc-url="docUrl" /> <!-- 使用自定义的 Word 预览组件 --> </div> </div> </template> <script> import WordPreview from './components/WordPreview.vue'; export default { components: { WordPreview }, data() { return { showDocument: false, docUrl: '' }; }, // 在适当的时候设置 docUrl 并更新 showDocument methods: { loadDocument() { // 加载并处理 Word 文档的逻辑 // 设置 docUrl 后更新 showDocument 为 true } }, created() { this.loadDocument(); } }; </script> ``` 在这个例子中,`WordPreview` 组件会负责显示文档内容,而导航栏则可以根据你的应用路由管理不同的页面状态。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值