HTML实现在线预览Excel,word,ppt
当从浏览器返回⼀个⽂件时,需要指定ContentType,以下是Office2007对应的值:
"application/vnd.plate" (for .dotx files)
"application/vnd.openxmlformats-officedocument.presentationml.presentation" (for .pptx files)
"application/vnd.openxmlformats-officedocument.presentationml.slideshow" (for .ppsx files)
"application/vnd.plate" (for .potx files)
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" (for .xlsx files)
"application/vnd.plate" (for .xltx files)
参考链接:
bug解决记录:
原来⽹站中有个需要,是下载Excel.
最开始实现的时候,是使⽤jsreport来实现,但是该服务收费,并且由于功能太强⼤了,学习成本⾼.
因为我们只是想要下载Excel,后⾯就了Excel.js这个库来实现.
下载Excel是没问题,⽣成⽂件流以后,,直接返回steam,有⼀天,领导说,需要在线预览Excel?
考虑过⼏种⽅案,
1. ⾃⼰实现解析Excel,直接以表格的样式返回HTML
2. 第三⽅js库,来实现Excel预览,
3. 其他(尽可能少改动现有代码)
但是测试了⼀下,发现并不能成功.因为我们服务器上通过接⼝下载Excel的URL拼接在上⾯src后⾯,不能预览,会报错.
最开始以为是https的问题,但是测试后发现,与https⽆关,https和http协议都能在线预览
也考虑过是不是URL上没⽤后缀,导致office⽆法识别该⽂件是什么类型,但是下载保存的时候,会⾃动识别出对应的⽂件后缀名,所以就肯定不是URL上没有后缀名导致的问题.
服务器后端使⽤的是Node.js,框架⽤的是express,如果将Excel放置在静态资源⽂件⽬录下,是能正常预览.
如果是将⽂件放在静态资源⽂件夹下访问,等同于调⽤express中的res.sendFile(filePath)⽅法.
我们的接⼝中,使⽤
res.set({
'Content-Disposition': 'Attachment; filename="report.xlsx'
});
来设置response的header,保证⽤户下载⽂件后存储到本地时默认是Excel后缀.
好,因为基础知识不牢,只能去查看express的源码中sendFile()⽅法有什么奥秘了
node_modules/express/lib/response.js
res.sendFile = function sendFile(path, options, callback) {
var done = callback;
var req = q;
var res = this;
var next = ;
var opts = options || {};
if (!path) {
throw new TypeError('path argument is required to res.sendFile');
}
// support function as second arg
if (typeof options === 'function') {
done = options;
opts = {};
}
if (! && !isAbsolute(path)) {
throw new TypeError('path must be absolute or specify root to res.sendFile');  }
// create file stream
var pathname = encodeURI(path);
var file = send(req, pathname, opts);
// transfer
sendfile(res, file, opts, function (err) {
if (done) return done(err);
if (err && de === 'EISDIR') return next();
// next() all but write errors
if (err && de !== 'ECONNABORTED' && err.syscall !== 'write') {
next(err);
}
});
};
可以看到,实际上sendFile调⽤的是node_modules/send/index.js⽅法,
在看send模块中的代码,发现
var mime = require('mime')
pe = function type (path) {
var res = s
if (Header('Content-Type')) return
var type = mime.lookup(path)
if (!type) {
debug('no content-type')
return
}
var charset = mime.charsets.lookup(type)
debug('content-type %s', type)
res.setHeader('Content-Type', type + (charset ? '; charset=' + charset : ''))
}
express在发送⽂件时,会调⽤上述代码,根据后缀名来获取Content-Type.
在查看mime的源码,会发现在mime中,require了⼀个type.json,⽽type.json就是各种后缀名对应的content-type
因为我们原来的代码中,只设置了Content-Disposition,代表该请求返回的是⼀个⽂件.
但是office365实际上是通过Content-Type来获取,当前需要预览的是什么类型的⽂件(word,ppt,Excel),所以,需要设置对应的Content-Type才能正确实现预览功能
mime库中type.json中后缀名对应的ContentType,可以⽤来做速查表
{
"application/andrew-inset": [
"ez"
],
"application/applixware": [
"aw"
],
"application/atom+xml": [
"atom"
],
"application/atomcat+xml": [
"atomcat"
],
"application/atomsvc+xml": [
"atomsvc"
],
"application/bdoc": [
"bdoc"
],
"application/ccxml+xml": [
"ccxml"
],
"application/cdmi-capability": [
"cdmia"
],
"application/cdmi-container": [
"cdmic"
],
"application/cdmi-domain": [
"cdmid"
]
,
"application/cdmi-object": [
"cdmio"
],
"application/cdmi-queue": [
"cdmiq"
],
"application/cu-seeme": [
"cu"
],
"application/dash+xml": [
"mpd"
],
"application/davmount+xml": [
"davmount"
],
"application/docbook+xml": [
"dbk"
],
"application/dssc+der": [
"dssc"
],
"application/ecmascript": [
"ecma"
],
"application/emma+xml": [
"emma"
],
"application/epub+zip": [
"epub"
],
"application/exi": [
"exi"
]
,
"application/font-tdpfr": [
"pfr"
],
"application/font-woff": [
"woff"
],
"application/font-woff2": [
"woff2"
],
"application/geo+json": [
"geojson"
],
"application/gml+xml": [
"gml"
],
"application/gpx+xml": [
"gpx"
],
"application/gxf": [
"gxf"
],
"application/gzip": [
"gz"
],
"application/hyperstudio": [
"stk"
],
"application/inkml+xml": [
"ink",
"inkml"
],
"application/ipfix": [
"ipfix"
],
"application/java-archive": [
"jar",
"war",
"ear"
],
"application/java-serialized-object": [    "ser"
],
"application/java-vm": [
"class"
]
,
"application/javascript": [
"js",
"mjs"
],
"application/json": [
"application/json5": [
"json5"
],
"application/jsonml+json": [
"jsonml"
]
,
"application/ld+json": [
"jsonld"
],
"application/lost+xml": [
"lostxml"
],
"application/mac-binhex40": [
"hqx"
],
"application/mac-compactpro": [
"cpt"
],
"application/mads+xml": [
"mads"
],
"application/manifest+json": [
"webmanifest"
],
"application/marc": [
"mrc"
],
"application/marcxml+xml": [
"mrcx"
],
"application/mathematica": [
"ma",
"nb",
"mb"
],
"application/mathml+xml": [
"mathml"
],
"application/mbox": [
"mbox"
],
"application/mediaservercontrol+xml": [    "mscml"
],
"application/metalink+xml": [
"metalink"
],
"application/metalink4+xml": [
"meta4"
],
gzip是什么文件夹
"application/mets+xml": [
"mets"
],
"application/mods+xml": [
"mods"
],
"application/mp21": [
"m21",
"mp21"
],
"application/mp4": [
"mp4s",