新项目前端用的是vue框架,后端用的是struts1框架(没错,就是struts1)。客户要求增加word上传的功能,这个功能在以前老项目里面已经存在,只需将jsp改造成vue。实际上,在改造过程中遇到了很多问题,记录下。
props: {
settings: {
docId: '', // 文档id,同时是文档名称
docFolder: '', // 文件夹名称,
fileExt: '.doc', // 文件扩展名:默认为.doc,如果你只上传word文档,这个不用改
width: '700', // 控件宽度
height: '500' // 控件高度
}
}
<!--
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>
data() {
return {
officeObj: null // ntko对象
}
}
/**
* 初始化文档控件,主要做以下操作:
* 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()
}
}
/**
* 下载office控件
*/
httpDownload() {
let fileName = this.settings.docId + '.doc'
let fileUrl = "/downloadOfficeOcx.do?fileName=" + fileName + "&docFolder=" + this.settings.docFolder
return this.officeObj.OpenFromURL(fileUrl, false)
}
/**
* 上传word文档
*/
httpUpload() {
let myUrl = "/uploadOfficeOcx.do"
let fileName = this.settings.docId + '.doc'
let params = "docFolder=" + this.settings.docFolder
/**
* officeFile:文件域的id,类似
return this.officeObj.saveToURL(myUrl, "officeFile", params, fileName, 0)
}
/**
* 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)
}
/* 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);
}
}
}
// 响应编码格式为gbk
response.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()返回的是文件名字普通域没有文件返回NULL
String 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;
}
}
watch: {
settings: {
handler(val){
this.settings = Object.assign(this.settings, val)
},
deep:true
}
}
<form-beans>
<form-bean name="officeUploadForm" type="xxx.xxx.xxx.OfficeUploadForm" />
form-beans>
<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>
第一个问题:这种问题出现在使用OfficeUploadForm去接收多个文件,由于上传时html和图片资源的name值都是一样的,struts1根据name值获取文件,由于只有一个name值,后来者把前面的都覆盖了,所以只有一个文件。
第二个问题:网上很多人推荐使用ServletFileUpload获取多文件,很方便强大。但是遇到struts1这个老顽固,就得小心了。因为ActionForm和ServletFileUpload不能同时存在,否则会接收不到文件。所以需要在xml中去掉uploadHtmlOcx的name值,同时把uploadHtmlOcx的返回值设为void。
这个问题在官网有记录,主要思路是:用一个iframe把整个ntko覆盖,设置iframe的z-index为一个很小的值,然后在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控件,都是垃圾!