潍坊mip网站建设,宁波外贸公司排行榜,社交型网站开发,织梦cms怎么做双语网站前端各种文本文件预览 文本编辑excel预览编辑 pdf预览word预览 excel下载pdf下载word下载
各种文本文件预览#xff08;pdf, xlsx, docx, cpp, java, sql, py, vue, html, js, json, css, xml, rust, md, txt, log, fa, fasta, tsv, csv 等各种文本文件#xff09; 其中 除p…前端各种文本文件预览 文本编辑excel预览编辑 pdf预览word预览 excel下载pdf下载word下载
各种文本文件预览pdf, xlsx, docx, cpp, java, sql, py, vue, html, js, json, css, xml, rust, md, txt, log, fa, fasta, tsv, csv 等各种文本文件 其中 除pdfxlsxdocx之外的文本还可以修改xlsx想要修改看我另一篇博客luckyexcel 编辑预览excel文件
先看效果
引入库
//预览编辑文本用codemirror/lang-cpp: ^6.0.2,codemirror/lang-css: ^6.2.1,codemirror/lang-html: ^6.4.9,codemirror/lang-java: ^6.0.1,codemirror/lang-javascript: ^6.2.2,codemirror/lang-json: ^6.0.1,codemirror/lang-markdown: ^6.2.5,codemirror/lang-python: ^6.1.6,codemirror/lang-rust: ^6.0.1,codemirror/lang-sql: ^6.7.0,codemirror/lang-vue: ^0.1.3,codemirror/lang-xml: ^6.1.0,codemirror/theme-one-dark: ^6.1.2,codemirror: ^6.0.1,//预览word、pdf、excel文件用vue-office/docx: ^1.6.2,vue-office/excel: ^1.7.11,vue-office/pdf: ^2.0.2,//导出wordbuffer: ^6.0.3,docxtemplater: ^3.46.0,file-saver: ^2.0.5,pizzip: ^3.1.6,jszip-utils: ^0.1.0,//导出pdfhtml2canvas: ^1.4.1,jspdf: ^2.5.1,//导出xlsx文件试用于electronweb也可以用node-xlsx: ^0.23.0,//或者用xlsx库xlsx: ^0.18.5导出pdf、xlsx、word文件
templatediv classcontent idexportPdfa-spacea-button typeprimary clickexportWord导出word/a-buttona-button typeprimary clickexportXlsx导出elcel/a-buttona-button typeprimary clickexportPdf导出pdf/a-buttona-button typeprimary click() router.push(/preview)文件预览/a-button/a-spacebr /br /hr /div classflex flex-justify-arounddivunocss/divdiv测试/divdiv可以用的/div/divbr /div classtext-centera hrefhttps://unocss.dev/interactive/ target_blank relnoopener noreferrerunocss 文档/a/div/div
/templatescript langts setupimport { useRouter } from vue-router;
import { setLogin, getUserInfo } from ../../serve/api/login;
import { globalData } from ../../setting/global;import { Buffer } from buffer;
import xlsx from node-xlsx;import docxtemplater from docxtemplater;
import PizZip from pizzip;
import JSZipUtils from jszip-utils;
import { saveAs } from file-saver;import html2canvas from html2canvas;
import JsPDF from jspdf;const router useRouter();const tableValue reactive({unit: 中国,date: undefined,sampleType: 你猜,people: 黄种人,name: 夜空,sex: 男,age: 25,work: 开发,id: ,jiance: 商品化试剂盒,date2: undefined,
});
const exportWord () {let docxname 导出word.docx;JSZipUtils.getBinaryContent(/template.docx, function (error: any, content: any) {// template.docx是模板这里我放到public公共文件夹下面了。我们在导出的时候会根据此模板来导出对应的数据// 抛出异常if (error) {throw error;}// 创建一个PizZip实例内容为模板的内容let zip new PizZip(content);// 创建并加载docx templater实例对象let doc new docxtemplater().loadZip(zip);// 设置模板变量的值 主要变量替换在这里doc.setData({name: tableValue.name,unit: tableValue.unit,date: 这里也不可以不写变量,sampleType: tableValue.sampleType,sex: tableValue.sex,age: tableValue.age,});try {// 用模板变量的值替换所有模板变量doc.render();} catch (error: any) {// 抛出异常let e {message: error.message,name: error.name,stack: error.stack,properties: error.properties,};console.log(JSON.stringify({error: e,}),);throw error;}// 生成一个代表docxtemplater对象的zip文件不是一个真实的文件而是在内存中的表示let out doc.getZip().generate({type: blob,mimeType: application/vnd.openxmlformats-officedocument.wordprocessingml.document,});// 将目标文件对象保存为目标类型的文件并命名saveAs(out, docxname);});
};
const exportXlsx () {let data [[1, 222, , , , ],[, 2, 3, 4, 5, 6],[, 2, 3, 4, 5, 6],[, 2, 3, 4, 5, 6],[, 2, 3, 4, 5, 6],[22, 2, 3, 4, 5, 6],];// 行列合并规则 ccol 列 r:row 行const range0 { s: { c: 0, r: 0 }, e: { c: 0, r: 4 } };const range1 { s: { c: 1, r: 0 }, e: { c: 5, r: 0 } };const sheetOptions {!merges: [range0, range1],// cols 列宽大小!cols: [{ wch: 5 }, { wch: 10 }, { wch: 15 }, { wch: 20 }, { wch: 30 }, { wch: 50 }],};//如果不需要格式这里的sheetOptions可以省略不写let result xlsx.build([{ name: sheet1, data }], { sheetOptions });const ab Buffer.from(result, binary);const blob new Blob([ab]);const blobUrl URL.createObjectURL(blob);const a document.createElement(a);a.href blobUrl;a.download 导出excel.xlsx;a.click();window.URL.revokeObjectURL(blobUrl);
};
const exportPdf () {downloadPDF(document.querySelector(#exportPdf), 导出pdf文件, pdfSuc(), 4);
};
const pdfSuc () {message.success(导出成功);
};
/*** ele:需要导出的容器* pdfName导出文件的名字* callback: 成功回调*/
const downloadPDF (ele: any, pdfName: any, callback: any, scale?: number) {html2canvas(ele, {dpi: 600,scale: scale ? scale : 8,// allowTaint: true, //允许 canvas 污染 allowTaint参数要去掉否则是无法通过toDataURL导出canvas数据的useCORS: true, //允许canvas画布内 可以跨域请求外部链接图片, 允许跨域请求。width: ele.scrollWidth,height: ele.scrollHeight,}).then((canvas) {//未生成pdf的html页面高度var leftHeight canvas.height;var a4Width 595.28;var a4Height 801.89; //一张A4高841.89减去20使得上下边距空出20,pdf.addImage生成上边距第四个参数10致使使得上下边距各10//一页pdf显示html页面生成的canvas高度;var a4HeightRef Math.floor((canvas.width / a4Width) * a4Height);//pdf页面偏移var position 0;var pageData canvas.toDataURL(image/jpeg, 1.0);var pdf new JsPDF(x, pt, a4);var index 1,canvas1 document.createElement(canvas),height;pdf.setDisplayMode(fullwidth, continuous, FullScreen);function createImpl(canvas) {if (leftHeight 0) {index;var checkCount 0;if (leftHeight a4HeightRef) {var i position a4HeightRef;for (i position a4HeightRef; i position; i--) {var isWrite true;for (var j 0; j canvas.width; j) {var c canvas.getContext(2d).getImageData(j, i, 1, 1).data;if (c[0] ! 0xff || c[1] ! 0xff || c[2] ! 0xff) {isWrite false;break;}}if (isWrite) {checkCount;if (checkCount 10) {break;}} else {checkCount 0;}}height Math.round(i - position) || Math.min(leftHeight, a4HeightRef);if (height 0) {height a4HeightRef;}} else {height leftHeight;}canvas1.width canvas.width;canvas1.height height;var ctx canvas1.getContext(2d);ctx.drawImage(canvas, 0, position, canvas.width, height, 0, 0, canvas.width, height);if (position ! 0) {pdf.addPage();}// 在pdf.addImage(pageData, JPEG, 左间距上间距宽度高度)设置在pdf中显示pdf.addImage(canvas1.toDataURL(image/jpeg, 1.0),JPEG,70,56,a4Width - 140,(a4Width / canvas1.width) * height - 112,);leftHeight - height;position height;if (leftHeight 0) {setTimeout(createImpl, 500, canvas);callback();} else {pdf.save(pdfName);callback();}}}// 当内容未超过pdf一页显示的范围无需分页if (leftHeight a4HeightRef) {pdf.addImage(pageData, JPEG, 0, 50, a4Width, (a4Width / canvas.width) * leftHeight);pdf.save(pdfName);// callback();} else {try {pdf.deletePage(0);setTimeout(createImpl, 500, canvas);} catch (err) {console.log(err);}}});
};
/scriptstyle langless scoped
.content {width: 90vw;min-height: 90vh;margin: 5vh auto;padding: 20px;outline: 1px dashed #999;
}
/style
预览各种文本
!--* Descripttion:* Author: 苍狼一啸八荒惊* Date: 2024-08-12 12:18:53* LastEditTime: 2024-08-13 15:27:27* LastEditors: 夜空苍狼啸
--
script langts setup
// ! 目前不支持doc、xls格式文件的预览
//引入VueOfficeDocx组件
import VueOfficeDocx from vue-office/docx;
import vue-office/docx/lib/index.css;//引入VueOfficeExcel组件
import VueOfficeExcel from vue-office/excel;
import vue-office/excel/lib/index.css;//引入VueOfficePdf组件
import VueOfficePdf from vue-office/pdf;import { message } from ant-design-vue;
import { useRouter } from vue-router;
const router useRouter();
const fileText: any undefined;
const data reactive({loading: false,fileList: [],fileType: xlsx,// docxSrc: http://static.shanhuxueyuan.com/test6.docx,// excelSrc: http://static.shanhuxueyuan.com/demo/excel.xlsx,docxSrc: ,excelSrc: /template.xlsx,pdfSrc: ,codemirror: false,fileText,refreshCodemirrorKey: 0,
});
const customUpload async (info: any) {data.loading true;console.log(info);let suffixName info.file.name.split(.).pop();data.fileType suffixName;data.codemirror false;let fileReader new FileReader();fileReader.readAsArrayBuffer(info.file);if ([docx, doc].includes(suffixName)) {if (suffixName doc) {message.info(请上传docx格式的文件);return;}fileReader.onload () {data.docxSrc fileReader.result;};} else if ([xlsx, xls].includes(suffixName)) {if (suffixName xls) {message.info(请上传xlsx格式的文件);return;}fileReader.onload () {data.excelSrc fileReader.result;};} else if ([pdf].includes(suffixName)) {fileReader.onload () {data.pdfSrc fileReader.result;};} else if ([cpp, java, sql, py, vue, html, js, json, css, xml, rust, md].includes(suffixName,)) {// 文本启用 Codemirrordata.codemirror true;data.fileText await readFileAsync(info.file);data.refreshCodemirrorKey;} else {// message.info(该格式暂不支持查看);data.codemirror true;data.fileText await readFileAsync(info.file);data.refreshCodemirrorKey;}data.loading false;
};
const handleChange async (e: any) {let file e.target.files[0];let suffixName file.name.split(.).pop();data.fileType suffixName;data.codemirror false;let fileReader new FileReader();fileReader.readAsArrayBuffer(file);if ([docx, doc].includes(suffixName)) {if (suffixName doc) {message.info(请上传docx格式的文件);return;}fileReader.onload () {data.docxSrc fileReader.result;};} else if ([xlsx, xls].includes(suffixName)) {if (suffixName xls) {message.info(请上传xlsx格式的文件);return;}// 使用blob文件流let blob new Blob([file], {type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,});data.excelSrc URL.createObjectURL(blob);// 读取文件的ArrayBuffer// fileReader.onload () {// data.excelSrc fileReader.result;// };// data.excelSrc URL.createObjectURL(file);} else if ([pdf].includes(suffixName)) {fileReader.onload () {data.pdfSrc fileReader.result;};} else if ([txt, vue, json, java, sql, js, css, xml, html, yaml, md, py].includes(suffixName,)) {// 文本启用 Codemirrordata.codemirror true;data.fileText await readFileAsync(file);data.refreshCodemirrorKey;} else {// message.info(该格式暂不支持查看);data.codemirror true;data.fileText await readFileAsync(file);data.refreshCodemirrorKey;}
};
const rendered () {console.log(渲染完成);
};
const errorHandler () {console.log(渲染失败);
};// 读取文本文件内容
const readFileAsync (file: Blob | File) {return new Promise((resolve, reject) {// 读取文件里面的内容返回var reader new FileReader();// 以文本格式读取文件reader.readAsText(file, UTF-8);reader.onload function (event) {resolve(event.target.result);};reader.onerror function (event) {reject(event.target);};});
};onMounted(() {});
/script
templatediv classcontentdiv classmb-1 color-red-500支持预览文件: pdf, xlsx, docx, cpp, java, sql, py, vue, html, js, json, css, xml, rust, md,txt, log, fa, fasta, tsv, csv 等各种文本文件/diva-space classmb-1!-- acceptapplication/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet --a-uploadv-model:file-listdata.fileList:customRequestcustomUploadnamefile:multiplefalse:showUploadListfalsea-button :loadingdata.loading typeprimary上传文件/a-button/a-uploadinput typefile reffileButton changehandleChange /a-button typeprimary click() router.push(/index)文件导出/a-button/a-space!-- office --div v-if!data.codemirror!-- docx --vue-office-docxv-ifdata.fileType docx:srcdata.docxSrcstyleheight: 80vhrenderedrenderederrorerrorHandler/!-- excel --vue-office-excelv-else-ifdata.fileType xlsx:srcdata.excelSrcstyleheight: 80vhrenderedrenderederrorerrorHandler/!-- pdf --vue-office-pdfv-else-ifdata.fileType pdf:srcdata.pdfSrcstyleheight: 100vhrenderedrenderederrorerrorHandler//div!-- 文本 --div v-else classmt--6Codemirror :fileTextdata.fileText :fileTypedata.fileType /!-- :keydata.refreshCodemirrorKey --/div/div
/templatestyle langless scoped
.content {width: 90vw;min-height: 90vh;margin: 5vh auto;padding: 20px;outline: 1px dashed #999;
}
/style
子组件
!--* Descripttion: * Author: 苍狼一啸八荒惊* Date: 2024-08-12 13:51:19* LastEditTime: 2024-08-13 15:36:07* LastEditors: 夜空苍狼啸
--script langts setup
// codemirror api https://codemirror.net/docs/guide/
import { EditorState, Text, Compartment } from codemirror/state;
import { basicSetup, EditorView } from codemirror;
import { keymap, lineNumbers } from codemirror/view;
import { defaultKeymap } from codemirror/commands;
import { oneDark } from codemirror/theme-one-dark;import { json, jsonParseLinter } from codemirror/lang-json;
import { css } from codemirror/lang-css;
import { cpp } from codemirror/lang-cpp;
import { html } from codemirror/lang-html;
import { java } from codemirror/lang-java;
import { javascript as js } from codemirror/lang-javascript;
import { markdown as md } from codemirror/lang-markdown;
import { python as py } from codemirror/lang-python;
import { sql } from codemirror/lang-sql;
import { rust } from codemirror/lang-rust;
import { vue } from codemirror/lang-vue;
import { xml } from codemirror/lang-xml;
import { saveTextAsFile } from //libs/utils/download;
const props defineProps({fileText: {type: String,default: hello word!, //文本},fileType: {type: String,default: json, // 编辑模式(文件类型)},
});const data reactive({fontSize: 14,theme: dark, // codeMirror主题readOnly: false,lineNumber: true,
});const editorRef: RefInstanceTypetypeof Element | undefined ref();onMounted(() {});
onUnmounted(() {view?.destroy();
});
watch(() props.fileText,(n) {init();},
);let view: any;
const init () {view?.destroy();let startState EditorState.create({doc: props.fileText,extensions: [data.lineNumber ? basicSetup : [],data.theme default ? [] : oneDark,EditorState.readOnly.of(!data.readOnly),textType(props.fileType),// 自定义主题// EditorView.theme(// {// : {// color: white,// backgroundColor: #034,// },// .cm-content: {// caretColor: #0e9,// },// .cm-focused .cm-cursor: {// borderLeftColor: #0e9,// },// .cm-focused .cm-selectionBackground, ::selection: {// backgroundColor: #074,// },// .cm-gutters: {// backgroundColor: #045,// color: #ddd,// border: none,// },// },// { dark: true },// ),],// extensions: [keymap.of(defaultKeymap)],});view new EditorView({state: startState,parent: unref(editorRef),});
};
const textType (type: string) {// if (supportType.includes(type)) {// // eval 将字符串转化为函数// return eval(type ());// } else {// return keymap.of(defaultKeymap);// }return type json? json(): type css? css(): type cpp? cpp(): type html? html(): type java? java(): type js || type ts? js(): type md? md(): type py? py(): type sql? sql(): type rust? rust(): type vue? vue(): type xml? xml(): keymap.of(defaultKeymap);
};
//节流
let timer_throttle: any;
const throttle (fn: Function, wait?: number) {wait wait || 100;if (!timer_throttle) {timer_throttle setTimeout(() {fn.apply(this);timer_throttle null;}, wait);}
};const handFontSize (value: string) {let cmContent document.querySelector(.cm-content);if (cmContent) {cmContent.style.fontSize value px;}
};
const handTheme (value: string) init();const handLineNumber (value: boolean) init();const handReadOnly (value: boolean) init();
const saveFile () {console.log(view?.state.doc.toString());saveTextAsFile(view?.state.doc.toString(), newFile. props.fileType);
};
/script
templatediv classflex-end mt-2 mb-2a-spacea-button typeprimary v-ifdata.readOnly clicksaveFile保存/a-buttona-select v-model:valuedata.fontSize classw-px-100 changehandFontSizea-select-option value1212px/a-select-optiona-select-option value1414px/a-select-optiona-select-option value1616px/a-select-optiona-select-option value1818px/a-select-option/a-selecta-select v-model:valuedata.theme classw-px-100 changehandThemea-select-option valuedefault默认/a-select-optiona-select-option valuedarkdark/a-select-option/a-selecta-switchchecked-children显示行号un-checked-children不显示v-model:checkeddata.lineNumberchangehandLineNumber/a-switchchecked-children可编辑un-checked-children不可编辑v-model:checkeddata.readOnlychangehandReadOnly//a-space/divdiv refeditorRef/div!-- CodemirrorCodemirror :valuefileText :fileType :lineNumber :readOnly :themedata.theme / --
/templatestyle langless scoped/style