前言

新项目前端用的是vue框架,后端用的是struts1框架(没错,就是struts1)。客户要求增加word上传的功能,这个功能在以前老项目里面已经存在,只需将jsp改造成vue。实际上,在改造过程中遇到了很多问题,记录下。

步骤

  1. ntko需要传递一些参数,我把它们写在props上,父组件使用时只需传递这些参数就可以了。
    props: {settings: {docId: '',  // 文档id,同时是文档名称docFolder: '',  // 文件夹名称,fileExt: '.doc', // 文件扩展名:默认为.doc,如果你只上传word文档,这个不用改width: '700',   // 控件宽度height: '500'  // 控件高度}}
  1. ntko是activex控件来着,使用方式如下:
<!--
xxxx:根据自己的情况填写
:width:绑定宽度
:height:绑定高度
-->
<object id='TANGER_OCX' classid='clsid:xxxxxxxxxxxx'codebase='../../../../public/lib/ntko-office/OfficeControl.cab#version=5,0,4,1':width='settings.width' :height='settings.height'><param name='TitleBar' value='0'><param name="NoExpireKey" value="xxxxxxxxxxxxxxxxxxxxx"><param name="MakerCaption" value="xxxxxxxxxxxxxxxxxxxxx"><param name="MakerKey" value="xxxxxxxxxxxxxxxxxxxxx"><param name="ProductCaption" value="xxxxxxxxxxxxxxxxxxxxx"><param name="ProductKey" value="xxxxxxxxxxxxxxxxxxxxx"><span style="color: red;display: inline-block">当前浏览器不能装载文档控件,请在检查浏览器的选项中检查浏览器的安全设置。</span>
</object>
  1. ntko的操作api需要一个ntko对象,所以需要一个属性存储ntko对象
    data() {return {officeObj: null  // ntko对象}}
  1. 初始化
      /*** 初始化文档控件,主要做以下操作:* 1. 封装ntko对象* 2. 判断docId是否为空,如果为空,则创建一个新的word文档;*     否则,根据docId去下载文档并显示出来*/initDoc(){// 获取控件对象this.officeObj = document.getElementById("TANGER_OCX")if (this.officeObj == null) {return}if (this.settings.docId == null || this.settings.docId === '') {// 打开一个空白文档this.officeObj.CreateNew('Word.Document')} else {// 下载文档this.httpDownload()}}
  1. 下载word文档:注意,这里下载的都是word文档,下载其他文档需要另作处理
      /*** 下载office控件*/httpDownload() {let fileName = this.settings.docId + '.doc'let fileUrl = "/downloadOfficeOcx.do?fileName=" + fileName + "&docFolder=" + this.settings.docFolderreturn this.officeObj.OpenFromURL(fileUrl, false)}
  1. 上传word文档
      /*** 上传word文档*/httpUpload() {let myUrl = "/uploadOfficeOcx.do"let fileName = this.settings.docId + '.doc'let params = "docFolder=" + this.settings.docFolder/*** officeFile:文件域的id,类似<input type=file id=officeFile 中的id* params:参数* 0:与控件一起提交的表单id,也可以是form的序列号,这里应该是0*/return this.officeObj.saveToURL(myUrl, "officeFile", params, fileName, 0)}
  1. 上传html文档
      /*** doc转HTML:会先上传word文档,然后再转换为html,再上传html文档*/saveDocAsHTML()  {//上传office文件this.httpUpload()//把文件保存到服务器let htmlFileName = this.settings.docId + ".html"let myUrl = "/uploadHtmlOcx.do?docId=" + this.settings.docId + "&docFolder=" + this.settings.docFolder//发布成html文件return this.officeObj.PublishAsHTMLToURL(myUrl, "uploadHtml", null, htmlFileName, 0)}
  1. 后台操作逻辑
 /* office和html的上传路径:根据实际情况写,一般从配置文件中读取 */private String officeUploadPath = "xxx/xxx/xxx";private String htmlUploadPath = "xxx/xxx/xxx";/*** 功能:下载office编辑文档信息*/public ActionForward downloadOfficeOcx(ActionMapping mapping,ActionForm form, HttpServletRequest request,HttpServletResponse response) throws Exception {String fileName = request.getParameter("fileName");InputStream inStream = null;try {String docFolder = request.getParameter("docFolder");String filePath = officeUploadPath + "/" + docFolder + "/"+ fileName;// 设置输出的格式response.reset();response.setContentType("bin");response.addHeader("Content-Disposition", "attachment; filename=\""+ fileName + "\"");File file = new File(filePath);if (!file.exists()) {// doc文档不存在时则创建一个return null;}// 读到流中inStream = new FileInputStream(filePath);// 文件的存放路径// 循环取出流中的数据byte[] b = new byte[100];int len;while ((len = inStream.read(b)) > 0)response.getOutputStream().write(b, 0, len);inStream.close();} catch (Exception e) {throw e;} finally {IOUtils.closeQuietly(inStream);}return null;}/*** 上传文档*/public ActionForward uploadOfficeOcx(ActionMapping mapping,ActionForm form, HttpServletRequest request,HttpServletResponse response) throws Exception {OfficeUploadForm officeUploadForm = (OfficeUploadForm) form;Hashtable<Object, Object> files = officeUploadForm.getMultipartRequestHandler().getFileElements();TreeMap<Object, Object> tree = new TreeMap<Object, Object>(files);// 上传文件StringBuffer message = new StringBuffer();if (!files.isEmpty()) {for (Object it : tree.keySet()) {FormFile formFile = (FormFile) files.get(it.toString());FileOutputStream fos = null;try {String docFolder = request.getParameter("docFolder");File file = new File(officeUploadPath + File.separator+ docFolder);if (!file.exists()) {file.mkdirs();// 文件夹找不到,创建文件夹}String officePath = officeUploadPath + File.separator+ docFolder + File.separator+ formFile.getFileName();fos = new FileOutputStream(new File(officePath));// 上传fos.write(formFile.getFileData());message.append("上传文件成功!");} catch (IOException e) {e.printStackTrace();message.append("上传文件失败!");} finally {IOUtils.closeQuietly(fos);}}}// 响应编码格式为gbkresponse.setCharacterEncoding("gbk");response.getWriter().print(message.toString());return null;}/*** 功能:保存为html文档*/public void uploadHtmlOcx(ActionMapping mapping, ActionForm form,HttpServletRequest request, HttpServletResponse response)throws Exception {String docFolder = request.getParameter("docFolder");String docId = request.getParameter("docId");String path = htmlUploadPath + File.separator + docFolder + File.separator + docId;try {DiskFileItemFactory factory = new DiskFileItemFactory();ServletFileUpload servletFileUpload = new ServletFileUpload(factory);List<FileItem> fileItems = servletFileUpload.parseRequest(request);for (FileItem fileItem : fileItems) {if (fileItem.isFormField()) {String FieldName = fileItem.getFieldName();// getName()返回的是文件名字普通域没有文件返回NULLString Content = fileItem.getString("UTF-8");request.setAttribute(FieldName, Content);} else {String nm = fileItem.getName().substring(fileItem.getName().lastIndexOf("\\") + 1);File file = new File(path);if (!file.exists()) {file.mkdirs();// 文件夹找不到,创建文件夹}File mkr = new File(path, nm);if (nm.indexOf(".html") > 0) {String html = getReadToString(fileItem.getInputStream(), "gb2312");StringBuilder sb = new StringBuilder();try {Parser parser = new Parser();parser.setInputHTML(html);parser.setEncoding("gb2312");NodeIterator it = parser.elements();while (it.hasMoreNodes()) {Node node = it.nextNode();node.accept(new NodeVisitor() {public void visitTag(Tag tag) {if (tag instanceof LinkTag) {LinkTag link = (LinkTag) tag;link.setAttribute("target","_blank");}}});sb.append(node.toHtml());}} catch (Exception e) {e.printStackTrace();}FileWriter fw = new FileWriter(mkr);fw.write(sb.toString());fw.close();} else {fileItem.write(mkr);}}}} catch (Exception e) {e.printStackTrace();}}private String getReadToString(InputStream is, String type) {StringBuffer data = new StringBuffer(1000);Reader reader = null;BufferedReader bufferReader = null;try {reader = new InputStreamReader(is, Charset.forName(type));bufferReader = new BufferedReader(reader);String line;while ((line = bufferReader.readLine()) != null) {data.append(line);data.append("\r\n");}} catch (Exception e) {e.printStackTrace();closeStream(is, bufferReader, reader);return "";} finally {closeStream(is, bufferReader, reader);return data.toString();}}/*** @param is* @param bufferReader* @param reader*/public static void closeStream(InputStream is, BufferedReader bufferReader,Reader reader) {try {if (bufferReader != null) {bufferReader.close();}} catch (IOException e1) {e1.printStackTrace();}try {if (reader != null) {reader.close();}} catch (IOException e1) {e1.printStackTrace();}try {if (is != null) {is.close();}} catch (IOException e1) {e1.printStackTrace();}}/*** word文件接收form*/
public class OfficeUploadForm extends BaseStrutsForm implements Serializable {private static final long serialVersionUID = -8000290643668685995L;private FormFile officeFile;public FormFile getOfficeFile() {return officeFile;}public void setOfficeFile(FormFile officeFile) {this.officeFile = officeFile;}}

采坑(问题)

  1. 父组件settings改变,为何子组件没有响应改变?原来以前都是监听值的改变,由于settings是对象,不能使用之前的办法监听了,所以采用以下做法。Object.assign的作用是合并两个对象。
    watch: {settings: {handler(val){this.settings = Object.assign(this.settings, val)},deep:true}}
  1. uploadOfficeOcx方法为什么后台接收不到文件?这里涉及到struts1的用法了,使用ActionForm的时候一定要记得在xml中配置
  <form-beans><form-bean name="officeUploadForm" type="xxx.xxx.xxx.OfficeUploadForm" /></form-beans>  <!-- 注意:哥就是这里没写name属性,才接收不到文件的 --><action name="officeUploadForm" path="//uploadOfficeOcx" parameter="uploadOfficeOcx" scope="request"type="org.springframework.web.struts.DelegatingActionProxy"></action><action name="officeUploadForm" path="/downloadOfficeOcx" parameter="downloadOfficeOcx" scope="request"type="org.springframework.web.struts.DelegatingActionProxy"></action><action path="/uploadHtmlOcx" parameter="uploadHtmlOcx" scope="request"type="org.springframework.web.struts.DelegatingActionProxy"></action>
  1. 上传单文件没问题,但是如果html中带有图片资源,相当于多文件上传,后台为什么只拿到最后一个文件?还有,我改成其他方法(ServletFileUpload),为什么一个文件也接收不了?

第一个问题:这种问题出现在使用OfficeUploadForm去接收多个文件,由于上传时html和图片资源的name值都是一样的,struts1根据name值获取文件,由于只有一个name值,后来者把前面的都覆盖了,所以只有一个文件。

第二个问题:网上很多人推荐使用ServletFileUpload获取多文件,很方便强大。但是遇到struts1这个老顽固,就得小心了。因为ActionForm和ServletFileUpload不能同时存在,否则会接收不到文件。所以需要在xml中去掉uploadHtmlOcx的name值,同时把uploadHtmlOcx的返回值设为void。

  1. 我使用了弹框组件,为什么会被ntko控件覆盖?怎么解决?

这个问题在官网有记录,主要思路是:用一个iframe把整个ntko覆盖,设置iframe的z-index为一个很小的值,然后在iframe上弹框。但是有个问题:iframe怎么设置透明,各位大佬,给我个思路。

<!-- 遮罩层:因为activex控件会始终显示在最上层 -->
<iframe v-if="isShade" src="javascript:false" allowtransparency="true" class="shade-iframe"></iframe>.shade-iframe {position:absolute;top:0px;left:0px;width:5000px;height:5000px;z-index:100;border-width:0px;background: #ff0000;opacity:0;}

总结

ntko坑很多,使用时建议结合旧项目(if exist)和ntko文档来,有问题记得上官网查询、或者百度。最后我想说的是:我不是针对ntko,我是针对在座的各位office web控件,都是垃圾!

vue使用ntko控件完成word上传、html上传相关推荐

  1. js html 导出word 不用activexobject,javascript下用ActiveXObject控件替换word书签,将内容导出到word后打印第2/2页...

    javascript下用ActiveXObject控件替换word书签,将内容导出到word后打印第2/2页 更新时间:2008年06月21日 22:57:31   作者: 由于时间比较紧,没多的时候 ...

  2. OA公文使用NTKO控件查看报错解决办法

    问题一.NTKO控件安装:"不能装载文档控件,请在检查浏览器的选项中检查浏览器的安全设置"问题 https://blog.csdn.net/iracer/article/detai ...

  3. C# WinForm中 获得当前鼠标所在控件 或 将窗体中鼠标所在控件名显示在窗体标题上...

    转:/********************** * 课题:将窗体中鼠标所在控件名显示在窗体标题上  * 作者:ZAXX  * QQ : 94027486  * 本课题可简单扩展:获取屏幕上鼠标所在 ...

  4. vue单位文本控件与vue加密文本控件

    vue单位文本控件: 使用方式: npm install dami-text-input --save使用:<text-input v-model="test" :unit= ...

  5. word保护视图的导致很多人打开异常或者ntko控件加载异常怎么处理

    对于word保护视图,对于公文系统管理员来说都很麻烦的.因为word保护视图文件在web页面ntko正文编辑控件会无法读取内容. 可以尝试如下办法去除保护视图: 1.把doc转换成html,再把htm ...

  6. 利用Aspose.Word控件实现Word文档的操作

    Aspose系列的控件,功能都挺好,之前一直在我的Winform开发框架中用Aspose.Cell来做报表输出,可以实现多样化的报表设计及输出,由于一般输出的内容比较正规化或者多数是表格居多,所以一般 ...

  7. aspose 换行写_利用Aspose.Word控件实现Word文档的操作

    Aspose系列的控件,功能都挺好,之前一直在我的Winform开发框架中用Aspose.Cell来做报表输出,可以实现多样化的报表设计及输出,由于一般输出的内容比较正规化或者多数是表格居多,所以一般 ...

  8. android 控件 堆叠_每次在Android上正确地向后堆叠

    android 控件 堆叠 When navigating in a mobile app, the screens opened after one another form a stack, th ...

  9. DevExpress控件使用系列--ASPxUploadControl(图片上传及预览)

    1.控件功能      列表控件展示数据.弹框控件执行编辑操作.Tab控件实现多标签编辑操官方说明 2.官方示例       2.1 ASPxImage                 http:// ...

  10. element ui 图片控件 排序_Element-ui上传图片后隐藏上存控件

    在使用Element-ui el-upload组件的时候,发现我只想上存一张图片,比如头像的上存,然而上存一张后,控件还可以继续上存. 一下的方法是Element-ui上传图片后隐藏上存控件. 在el ...

最新文章

  1. python输出数据到excel-python实现数据导出到excel的示例
  2. java调用matlab 数组_JAVA调用matlab程序 输入输出数据转换
  3. 【深度学习】擦除:提升 CNN 特征可视化的 3 种重要手段
  4. 缓冲池、String/StringBuffer/StringBuilder、intern()
  5. ASP.NET MVC中使用FluentValidation验证实体
  6. IO对象不可以复制或者赋值
  7. tomcat的根路径设置
  8. HTML5数据推送SSE原理及应用开发
  9. 20应用统计考研复试要点(part6)--统计学
  10. 四万字让你精通SQL数据库操作
  11. MTK 驱动---(8)emmc 介绍
  12. 视频转音频时,安卓和iOS播放的时长翻倍 --- 好一个坑
  13. Maven学习总结(45)——Maven仓库、将本地Jar包安装到仓库、打可执行的Jar总结
  14. RabbitMQ的web界面解析
  15. python语法学习之对象与参考,局部与全局变量
  16. 计算机教室布线施工方案,最新计算机教室施工方案.docx
  17. android 项目交接文档,Android实用开发规范
  18. 2018-2019-1 20165301 20165304 20165314 实验二 固件程序设计
  19. IT技术员的发展方向和晋升秘笈
  20. 什么是Token(令牌)

热门文章

  1. ILSPY反编译工具下载代替收费的Reflector工具
  2. GIS应用技巧之世界各国矢量获取途径
  3. gwr模型用什么做_干货|教你如何用Stata做二元选择模型
  4. 【word小技巧】将visio图插入到word中
  5. 64位驱动签名工具64Signer
  6. android 生成车牌号,android 车牌号识别系统app源码
  7. 利用EGM96和EGM2008模型,分别计算计算高程异常、重力异常和垂线偏差。
  8. zmap扫描mysql_45分钟扫遍全网:最快的互联网扫描工具ZMap
  9. Scala深入浅出实战初级入门经典视频课程
  10. 硬盘低格工具HDD Low Level Format Tool 4.30注册版