Gitee仓库
https://gitee.com/Lin_DH/system
介绍
文件预览功能是指在不打开或编辑文件的情况下,通过某种方式查看文件的内容、格式或者部分内容的功能。该功能通常用于文件管理系统、办公工具、在线教育平台、企业协作平台、电子邮件客户端等领域,能够提高用户体验,节省带宽和存储空间,并保护知识产权。
今天推荐一个用 SpringBoot 搭建的文档在线预览解决方案:kkFileView。
官网
https://kkfileview.keking.cn/zh-cn/index.html
运行项目
第一步:下载源码
https://github.com/kekingcn/kkFileView
第二步:用 IDEA 打开源码
第三步:配置 Maven
第四步:配置文件编码
第五步:配置编译环境
第六步:双击 Ctrl 键,输入打包命令:mvn package
打包获得 linux 环境运行的 kkFileView-x.x.x.tar.gz 和 window 环境运行的 kkFileView-x.x.x.zip,解压 .zip 文件获得 kkFileView-x.x.x 文件。
第七步:运行 kkFileView-x.x.x 文件中 bin 目录的 startup.bat 文件。
浏览器访问 http://127.0.0.1:8012/,成功运行项目访问到页面。
第八步:获取 base64 cdn
https://www.jsdelivr.com/package/npm/js-base64
三种调用方式
1)普通文件下载url预览
<script type="text/javascript"src="https://cdn.jsdelivr.net/npm/js-base64@3.6.0/base64.min.js"></script>
varurl = 'http://127.0.0.1:8080/file/test_.txt'; //要预览文件的访问地址
window.open('http://127.0.0.1:8012/onlinePreview?url='+encodeURIComponent(Base64.encode(url)));
2)http / https下载流 url 预览
<script type="text/javascript"src="https://cdn.jsdelivr.net/npm/js-base64@3.6.0/base64.min.js"></script>
varoriginUrl = 'http://127.0.0.1:8080/filedownload?fileId=1'; //要预览文件的访问地址
varpreviewUrl = originUrl + '&fullfilename=test.txt';
window.open('http://127.0.0.1:8012/onlinePreview?url='+encodeURIComponent(Base64.encode(previewUrl)));
3)FTP方式
<script type="text/javascript"src="https://cdn.jsdelivr.net/npm/js-base64@3.6.0/base64.min.js"></script>
varurl = 'ftp://127.0.0.1/file/test.txt'; //要预览文件的访问地址
window.open('http://127.0.0.1:8012/onlinePreview?url='+encodeURIComponent(Base64.encode(url)));
第九步:配置静态文件位置
application.yml
spring:mvc:static-path-pattern: /static/**
在 resources 目录下,新建 static 目录,image 目录,并放入文件。
第十步:放入 js-base64 文件
在 static 目录下,新建 js 目录,放入 js-base64-v3.6.0.js 文件。
js-base64-v3.6.0.js
//
// THIS FILE IS AUTOMATICALLY GENERATED! DO NOT EDIT BY HAND!
//
;(function(global, factory) {typeof exports === 'object' && typeof module !== 'undefined'? module.exports = factory(): typeof define === 'function' && define.amd? define(factory) :// cf. https://github.com/dankogai/js-base64/issues/119(function() {// existing version for noConflict()const _Base64 = global.Base64;const gBase64 = factory();gBase64.noConflict = () => {global.Base64 = _Base64;return gBase64;};if (global.Meteor) { // Meteor.jsBase64 = gBase64;}global.Base64 = gBase64;})();
}((typeof self !== 'undefined' ? self: typeof window !== 'undefined' ? window: typeof global !== 'undefined' ? global: this
), function() {'use strict';/*** base64.ts** Licensed under the BSD 3-Clause License.* http://opensource.org/licenses/BSD-3-Clause** References:* http://en.wikipedia.org/wiki/Base64** @author Dan Kogai (https://github.com/dankogai)*/
const version = '3.6.0';
/*** @deprecated use lowercase `version`.*/
const VERSION = version;
const _hasatob = typeof atob === 'function';
const _hasbtoa = typeof btoa === 'function';
const _hasBuffer = typeof Buffer === 'function';
const _TD = typeof TextDecoder === 'function' ? new TextDecoder() : undefined;
const _TE = typeof TextEncoder === 'function' ? new TextEncoder() : undefined;
const b64ch = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
const b64chs = [...b64ch];
const b64tab = ((a) => {let tab = {};a.forEach((c, i) => tab[c] = i);return tab;
})(b64chs);
const b64re = /^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/;
const _fromCC = String.fromCharCode.bind(String);
const _U8Afrom = typeof Uint8Array.from === 'function'? Uint8Array.from.bind(Uint8Array): (it, fn = (x) => x) => new Uint8Array(Array.prototype.slice.call(it, 0).map(fn));
const _mkUriSafe = (src) => src.replace(/[+\/]/g, (m0) => m0 == '+' ? '-' : '_').replace(/=+$/m, '');
const _tidyB64 = (s) => s.replace(/[^A-Za-z0-9\+\/]/g, '');
/*** polyfill version of `btoa`*/
const btoaPolyfill = (bin) => {// console.log('polyfilled');let u32, c0, c1, c2, asc = '';const pad = bin.length % 3;for (let i = 0; i < bin.length;) {if ((c0 = bin.charCodeAt(i++)) > 255 ||(c1 = bin.charCodeAt(i++)) > 255 ||(c2 = bin.charCodeAt(i++)) > 255)throw new TypeError('invalid character found');u32 = (c0 << 16) | (c1 << 8) | c2;asc += b64chs[u32 >> 18 & 63]+ b64chs[u32 >> 12 & 63]+ b64chs[u32 >> 6 & 63]+ b64chs[u32 & 63];}return pad ? asc.slice(0, pad - 3) + "===".substring(pad) : asc;
};
/*** does what `window.btoa` of web browsers do.* @param {String} bin binary string* @returns {string} Base64-encoded string*/
const _btoa = _hasbtoa ? (bin) => btoa(bin): _hasBuffer ? (bin) => Buffer.from(bin, 'binary').toString('base64'): btoaPolyfill;
const _fromUint8Array = _hasBuffer? (u8a) => Buffer.from(u8a).toString('base64'): (u8a) => {// cf. https://stackoverflow.com/questions/12710001/how-to-convert-uint8-array-to-base64-encoded-string/12713326#12713326const maxargs = 0x1000;let strs = [];for (let i = 0, l = u8a.length; i < l; i += maxargs) {strs.push(_fromCC.apply(null, u8a.subarray(i, i + maxargs)));}return _btoa(strs.join(''));};
/*** converts a Uint8Array to a Base64 string.* @param {boolean} [urlsafe] URL-and-filename-safe a la RFC4648 §5* @returns {string} Base64 string*/
const fromUint8Array = (u8a, urlsafe = false) => urlsafe ? _mkUriSafe(_fromUint8Array(u8a)) : _fromUint8Array(u8a);
// This trick is found broken https://github.com/dankogai/js-base64/issues/130
// const utob = (src: string) => unescape(encodeURIComponent(src));
// reverting good old fationed regexp
const cb_utob = (c) => {if (c.length < 2) {var cc = c.charCodeAt(0);return cc < 0x80 ? c: cc < 0x800 ? (_fromCC(0xc0 | (cc >>> 6))+ _fromCC(0x80 | (cc & 0x3f))): (_fromCC(0xe0 | ((cc >>> 12) & 0x0f))+ _fromCC(0x80 | ((cc >>> 6) & 0x3f))+ _fromCC(0x80 | (cc & 0x3f)));}else {var cc = 0x10000+ (c.charCodeAt(0) - 0xD800) * 0x400+ (c.charCodeAt(1) - 0xDC00);return (_fromCC(0xf0 | ((cc >>> 18) & 0x07))+ _fromCC(0x80 | ((cc >>> 12) & 0x3f))+ _fromCC(0x80 | ((cc >>> 6) & 0x3f))+ _fromCC(0x80 | (cc & 0x3f)));}
};
const re_utob = /[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g;
/*** @deprecated should have been internal use only.* @param {string} src UTF-8 string* @returns {string} UTF-16 string*/
const utob = (u) => u.replace(re_utob, cb_utob);
//
const _encode = _hasBuffer? (s) => Buffer.from(s, 'utf8').toString('base64'): _TE? (s) => _fromUint8Array(_TE.encode(s)): (s) => _btoa(utob(s));
/*** converts a UTF-8-encoded string to a Base64 string.* @param {boolean} [urlsafe] if `true` make the result URL-safe* @returns {string} Base64 string*/
const encode = (src, urlsafe = false) => urlsafe? _mkUriSafe(_encode(src)): _encode(src);
/*** converts a UTF-8-encoded string to URL-safe Base64 RFC4648 §5.* @returns {string} Base64 string*/
const encodeURI = (src) => encode(src, true);
// This trick is found broken https://github.com/dankogai/js-base64/issues/130
// const btou = (src: string) => decodeURIComponent(escape(src));
// reverting good old fationed regexp
const re_btou = /[\xC0-\xDF][\x80-\xBF]|[\xE0-\xEF][\x80-\xBF]{2}|[\xF0-\xF7][\x80-\xBF]{3}/g;
const cb_btou = (cccc) => {switch (cccc.length) {case 4:var cp = ((0x07 & cccc.charCodeAt(0)) << 18)| ((0x3f & cccc.charCodeAt(1)) << 12)| ((0x3f & cccc.charCodeAt(2)) << 6)| (0x3f & cccc.charCodeAt(3)), offset = cp - 0x10000;return (_fromCC((offset >>> 10) + 0xD800)+ _fromCC((offset & 0x3FF) + 0xDC00));case 3:return _fromCC(((0x0f & cccc.charCodeAt(0)) << 12)| ((0x3f & cccc.charCodeAt(1)) << 6)| (0x3f & cccc.charCodeAt(2)));default:return _fromCC(((0x1f & cccc.charCodeAt(0)) << 6)| (0x3f & cccc.charCodeAt(1)));}
};
/*** @deprecated should have been internal use only.* @param {string} src UTF-16 string* @returns {string} UTF-8 string*/
const btou = (b) => b.replace(re_btou, cb_btou);
/*** polyfill version of `atob`*/
const atobPolyfill = (asc) => {// console.log('polyfilled');asc = asc.replace(/\s+/g, '');if (!b64re.test(asc))throw new TypeError('malformed base64.');asc += '=='.slice(2 - (asc.length & 3));let u24, bin = '', r1, r2;for (let i = 0; i < asc.length;) {u24 = b64tab[asc.charAt(i++)] << 18| b64tab[asc.charAt(i++)] << 12| (r1 = b64tab[asc.charAt(i++)]) << 6| (r2 = b64tab[asc.charAt(i++)]);bin += r1 === 64 ? _fromCC(u24 >> 16 & 255): r2 === 64 ? _fromCC(u24 >> 16 & 255, u24 >> 8 & 255): _fromCC(u24 >> 16 & 255, u24 >> 8 & 255, u24 & 255);}return bin;
};
/*** does what `window.atob` of web browsers do.* @param {String} asc Base64-encoded string* @returns {string} binary string*/
const _atob = _hasatob ? (asc) => atob(_tidyB64(asc)): _hasBuffer ? (asc) => Buffer.from(asc, 'base64').toString('binary'): atobPolyfill;
//
const _toUint8Array = _hasBuffer? (a) => _U8Afrom(Buffer.from(a, 'base64')): (a) => _U8Afrom(_atob(a), c => c.charCodeAt(0));
/*** converts a Base64 string to a Uint8Array.*/
const toUint8Array = (a) => _toUint8Array(_unURI(a));
//
const _decode = _hasBuffer? (a) => Buffer.from(a, 'base64').toString('utf8'): _TD? (a) => _TD.decode(_toUint8Array(a)): (a) => btou(_atob(a));
const _unURI = (a) => _tidyB64(a.replace(/[-_]/g, (m0) => m0 == '-' ? '+' : '/'));
/*** converts a Base64 string to a UTF-8 string.* @param {String} src Base64 string. Both normal and URL-safe are supported* @returns {string} UTF-8 string*/
const decode = (src) => _decode(_unURI(src));
/*** check if a value is a valid Base64 string* @param {String} src a value to check*/
const isValid = (src) => {if (typeof src !== 'string')return false;const s = src.replace(/\s+/g, '').replace(/=+$/, '');return !/[^\s0-9a-zA-Z\+/]/.test(s) || !/[^\s0-9a-zA-Z\-_]/.test(s);
};
//
const _noEnum = (v) => {return {value: v, enumerable: false, writable: true, configurable: true};
};
/*** extend String.prototype with relevant methods*/
const extendString = function () {const _add = (name, body) => Object.defineProperty(String.prototype, name, _noEnum(body));_add('fromBase64', function () { return decode(this); });_add('toBase64', function (urlsafe) { return encode(this, urlsafe); });_add('toBase64URI', function () { return encode(this, true); });_add('toBase64URL', function () { return encode(this, true); });_add('toUint8Array', function () { return toUint8Array(this); });
};
/*** extend Uint8Array.prototype with relevant methods*/
const extendUint8Array = function () {const _add = (name, body) => Object.defineProperty(Uint8Array.prototype, name, _noEnum(body));_add('toBase64', function (urlsafe) { return fromUint8Array(this, urlsafe); });_add('toBase64URI', function () { return fromUint8Array(this, true); });_add('toBase64URL', function () { return fromUint8Array(this, true); });
};
/*** extend Builtin prototypes with relevant methods*/
const extendBuiltins = () => {extendString();extendUint8Array();
};
const gBase64 = {version: version,VERSION: VERSION,atob: _atob,atobPolyfill: atobPolyfill,btoa: _btoa,btoaPolyfill: btoaPolyfill,fromBase64: decode,toBase64: encode,encode: encode,encodeURI: encodeURI,encodeURL: encodeURI,utob: utob,btou: btou,decode: decode,isValid: isValid,fromUint8Array: fromUint8Array,toUint8Array: toUint8Array,extendString: extendString,extendUint8Array: extendUint8Array,extendBuiltins: extendBuiltins,
};//// export Base64 to the namespace//// ES5 is yet to have Object.assign() that may make transpilers unhappy.// gBase64.Base64 = Object.assign({}, gBase64);gBase64.Base64 = {};Object.keys(gBase64).forEach(k => gBase64.Base64[k] = gBase64[k]);return gBase64;
}));
第十一步:编写文件预览页面
filePreview.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head lang="en"><meta charset="UTF-8" /><title>文件预览页面</title><script type="text/javascript" th:src="@{../static/js/js-base64-v3.6.0.js}"></script>
</head><body>
<h1>文件预览页面</h1>
<button th:onclick="'previewFile();'">预览</button>
</body><script th:inline="javascript">function previewFile () {const domain = "http://127.0.0.1";const fileUrl = domain + ":8888/static/image/Avatar.jpg";//const fileUrl = domain + ":8888/static/js/js-base64-v3.6.0.js";const url = domain + ":8012/onlinePreview?url=" + encodeURIComponent(Base64.encode(fileUrl));window.open(url);}
</script></html>
第十二步:编写文件访问类
FileController.java
/*** @author DUHAOLIN* @date 2024/10/15*/
@Controller
public class FileController {@GetMapping("filePreview")public String filePreview() {return "filePreview";}}
效果图