为什么要读取图片呢?需求来源于这里。我有一大堆的ppt文件,里面全是图片,想将这些图片全部拿到,然后存储在数据库中,在线上预览,一张张的保存我自然是不乐意的。
找了一大堆文档都是读取pptx,没有读取ppt
的怎么办,先转为pptx
吧,于是有了批量将ppt格式转为pptx格式的文章...
相关模块或文档
- js-pptx : https://github.com/won21kr/js-pptx
- jszip : https://www.npmjs.com/package/jszip
- xml2js : https://www.npmjs.com/package/xml2js
大体思路
其实高版本的pptx 也好,docx也好,本质上是一个压缩文件,我们完全可以将他的后缀改为rar
或 zip
然后解压,就可以拿到里面的xml 或 资源文件,所以,思路就是将文档通过jszip
解压获取内部的文件,然后读取xml
找到对应的关系,然后将image
读取出来进行保存。
实现代码
/**
* 读取目录下的pptx 文件,并得到ppt的各个页面的截图数据,然后进行处理成为结构化数据。
* @author chrunlee
*/
const JSZIP = require('jszip');
const fs = require('fs');
const path = require('path');
const xml2js = require('xml2js');
/**
* 获取ppt内各个slide对应的图片路径,含多张图片
* @param {Strin}} filePath pptx filepath
*/
function getSliders (filePath/**pptx filePath */,targetFolder) {
let data = fs.readFileSync(filePath)
const zip = new JSZIP();
return new Promise((r, j) => {
//加载pptx数据
zip.loadAsync(data).then(async zip => {
let files = Object.keys(zip.files).filter(t => {
return t.startsWith('ppt/slides') && path.extname(t) == '.rels';
})
//做文件名排序
files.sort((a, b) => {
let asq = path.basename(a).substr(0, path.basename(a).indexOf('.')).replace('slide', '');
let bsq = path.basename(b).substr(0, path.basename(b).indexOf('.')).replace('slide', '');
return asq - bsq;
})
let sliders = [];
for (let file of files) {
//读取xml内容
let content = await zip.file(file).async('string');
let obj = await xml2js.parseStringPromise(content);
//获取关联关系
let relationship = obj.Relationships.Relationship;//[[]]
let arr = relationship.filter(ship => {
return path.extname(ship.$.Target) == '.jpeg' || path.extname(ship.$.Target) == '.png'
}).map(ship => {
return {
id: ship.$.Id.replace('rId',''),
filePath: 'ppt/'+ship.$.Target.substr(3)
}
}).sort((a, b) => {
return a.id - b.id;
})
sliders.push(arr);
}
//将图片进行存储,并返回真实路径
let fileArr = [];
fs.mkdirSync(targetFolder, { recursive: true });
for (let arr of sliders) {
let objarr = [];
if (arr && arr.length > 0) {
for (let obj of arr) {
let stream = await zip.file(obj.filePath).async('nodebuffer');
let realFilePath = path.join(targetFolder, path.basename(obj.filePath));
fs.writeFileSync(realFilePath,stream);
objarr.push({
id : obj.id,filePath : realFilePath
})
}
}
fileArr.push(objarr);
}
r(fileArr);
})
})
}
(async function () {
let sliders = await getSliders('./蓝天空.pptx', 'd:/nodejs/toy/ppt转pptx读取/image/蓝天空/');
})();
通过读取ppt/slides/_rels/***.rels
文件,来获得该slide
中对应的图片,找到对应的关系,然后通过jszip
来获得该图片数据流进行保存,思路很简单,主要还是对使用的模块的api不熟悉,找了不少资料。
仔细看ppt
还会发现,有大部分ppt
中一页有多张图片是拼接起来的...其实我是想讲多张图片合并为一张图片进行保存的。
当然,合并图片的就不在这里面写了,是另外一篇文章了,等我后续更新吧。
实现方式还是通过gm
来进行合并,命令超级简单..就是安装费劲。