1.准备工作
1.1.添加上传必要jar包
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
1.2.springmvc xml配置
<!-- SpringMVC上传文件时,需要配置MultipartResolver处理器 -->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="UTF-8" />
<!-- 指定所上传文件的总大小,单位字节。注意maxUploadSize属性的限制不是针对单个文件,而是所有文件的容量之和 -->
<property name="maxUploadSize" value="10240000" />
</bean>
2.前端页面代码
注意不论是上传 图片还是 doc文档等,前端写法都一样,只是后端解析工具类不一样而已
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>ajax请求上传文件</title>
<script type="text/javascript" src="/static/js/jquery.min.js"></script>
</head>
<body>
<%--页面按钮--%>
<button id="addImport">导入</button>
<%--隐藏的文件输入框--%>
<input id="FileUpload" name="file" type="file" onchange="uploadWord()" style="display: none"/>
</body>
<script type="text/javascript">
/**
* 导入word文档入口
*/
$('#addImport').click(function () {
openFileDialogue();
});
/**
* 打开上传文件对话框
*/
function openFileDialogue() {
var f = document.getElementById('FileUpload');
f.click();
} /**
* 文件上传 前检查与确认
*/
var msg;
function uploadWord() {
var fileObj = document.getElementById("FileUpload").files[0]; // js 获取文件对象
var fileObjName = $("#FileUpload").val();
if (typeof (fileObj) == "undefined" || fileObj.size <= 0) {
alert("请选择要导入的文档?");
return;
}
//判断是否为 doc 或 docx 文件
var fileName = getFileName(fileObjName);
var fileSuffix = getFileSuffix(fileObjName);
if (fileSuffix != 'doc' && fileSuffix != 'docx') {
alert("----请选择正确的文件格式---------");
return;
}
//确认是否上传(略)
//执行上传
uploadWordDo(fileObj, fileName); } /**
* 发送ajax请求 执行上传
*/
function uploadWordDo(fileObj) {
var formFile = new FormData();
formFile.append("file", fileObj); //加入文件对象
formFile.append("basePath", ""); //加入文件对象
var data = formFile;
$.ajax({
url: "/upload/do",
data: data,
type: "Post",
dataType: "json",
async: true,
cache: false,
processData: false,//用于对data参数进行序列化处理 这里必须false
contentType: false, //必须
success: function (result) {
//成功提示
var code = result.code;
if (code == '0000') {
alert("--上传成功---");
} else {
alert("--失败---");
}
}
});
}
/**
* 获取文件名
* @param file
* @returns {*}
*/
function getFileName(file) {
var arr = file.split('\\');
return arr[arr.length - 1];
} /**
* 获取后缀
* @param file
* @returns {string}
*/
function getFileSuffix(file) {
var point = file.lastIndexOf(".");
var type = file.substr(point + 1);
return type;
} </script>
</html>
3.后端处理
后端controller主要有两个方法,一个是获取上传页面的方法,另一个是处理上传的方法
package com.linrain.jcs.controller.bbsNews; import com.alibaba.fastjson.JSONObject;
import com.linrain.jcs.constant.CommonConstant;
import com.linrain.jcs.tool.DateUtil;
import com.linrain.jcs.tool.downPOI.baseDown.PoiUtil;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletRequest;
import java.io.InputStream; /**
* 文件上传
* Created by 姿势帝 on 2018/7/20.
* WX: 851298348
*/
@Controller
@RequestMapping(value = "/upload")
public class UploadController { /**
* 文件上传页面
*
* @return
*/
@RequestMapping(value = "/page")
public String page() { return "bbsNews/upload";
} /**
* 上传doc 或 docx
*
* @param file
* @return
*/
@RequestMapping(value = "/do", method = RequestMethod.POST)
@ResponseBody
public Object doUploadFile(@RequestParam("file") MultipartFile file, HttpServletRequest request, String basePath) {
JSONObject jsonObject = new JSONObject();
if (!file.isEmpty()) {
try {
InputStream inputStream = file.getInputStream();
String originalFilename = file.getOriginalFilename();
String fileName = DateUtil.getTimeString() + originalFilename;
//文件处理工具类(以后什么文件,这里就调用什么处理工具就可以了,这里是将上传的doc文件转变为html文件)
String con = PoiUtil.getHtml(inputStream, fileName);
jsonObject.put("content", con);
jsonObject.put("success", true);
jsonObject.put("code", CommonConstant.CODE_SUCCESS);
return jsonObject;
} catch (Exception e) {
e.printStackTrace(); }
}
jsonObject.put("success", false);
jsonObject.put("code", CommonConstant.CODE_IMPORT_FALSE);
jsonObject.put("msg", "文档导入失败!");
return jsonObject;
}
}
4.工具处理类
该工具类中主要处理 将doc或docx转变为--html文件
package com.linrain.jcs.tool.downPOI.baseDown; /**
* Created by Administrator on 2018/11/29.
*/ import com.linrain.jcs.tool.ConfigUtil;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.converter.PicturesManager;
import org.apache.poi.hwpf.converter.WordToHtmlConverter;
import org.apache.poi.hwpf.usermodel.PictureType;
import org.apache.poi.xwpf.converter.core.BasicURIResolver;
import org.apache.poi.xwpf.converter.core.FileImageExtractor;
import org.apache.poi.xwpf.converter.xhtml.XHTMLConverter;
import org.apache.poi.xwpf.converter.xhtml.XHTMLOptions;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document; import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.*;
import java.util.UUID; /**
* Created by 姿势帝 on 2018/11/299.
* 使用poi将word转为html文件,并从文件中读取内容
* wx:851298348
*/
public class PoiUtil {
private static final Logger log = LoggerFactory.getLogger(PoiUtil.class);
// 在html中图片保存的相对路径 static/images/upload
// private static String imagePath = "\\static\\images\\upload\\";
private static String imagePath = ConfigUtil.getTempImagePath();
private static String imagePathStr; //图片绝对地址
public static String rootPath;//项目跟路径
public static Long tempTime;//项目跟路径 /**
* 初始换图片地址
*/
static {
RegexAnswerUtil regexAnswerUtil = new RegexAnswerUtil();
rootPath = regexAnswerUtil.getRootPath();
imagePathStr = rootPath + imagePath;
log.info(" imagePathStr = " + imagePathStr);
tempTime = ConfigUtil.getTempTime();
} /**
* 更具文件名称判断是否超时
*/
public static boolean haveOvertime(String fileName) {
boolean flag = false;
if (fileName == null || fileName.length() < 14) {
return flag;
}
try {
String substring = fileName.substring(0, 13);
Long fileTime = Long.valueOf(substring);
Long nowTime = System.currentTimeMillis();
long l = nowTime - fileTime;
// long time = 2 * 60 * 60 * 1000; // 2个小时
//long time = 2 * 60 * 1000; // 2 分钟
if (l > tempTime) {
flag = true;
}
} catch (Exception e) {
e.printStackTrace();
}
return flag;
} /**
* 删除文件
*/
public static void del() {
File file = new File(imagePathStr);
delete(file);
} /**
* 根据地址删除文件
*
* @param path
*/
public static void deletePic(String path) {
File file = new File(path);
boolean delete = file.delete();
log.info(" delete=" + delete + "path=" + path);
} public static String getTimeUUID() {
String s = UUID.randomUUID().toString();
s = s.substring(0, 4);
return System.currentTimeMillis() + "-word" + s;
} /**
* 根据文件递归删除
*
* @param file
*/
public static void delete(File file) {
if (!file.exists()) return;
if (file.isFile() || file.list() == null) {
String path = file.getPath();
String name = file.getName();
if (haveOvertime(name)) {
boolean delete = file.delete();
log.info("delete=" + delete + " path=" + path);
} else {
log.info("该文不符合删除条件 path=" + path);
} } else {
File[] files = file.listFiles();
for (File a : files) {
delete(a);
}
boolean delete = file.delete();
log.info("删除文件夹 delete =" + delete + " path=" + file.getPath());
}
} /**
* @param inputStream word文件的File对象
* @param sourceFileName word文件名
* @return 转成的html字符串
*/
public static String getHtml(InputStream inputStream, String sourceFileName) throws Exception {
String content;
// 判断word文档类型,使用不同方法进行转换
if (sourceFileName.endsWith(".doc")) {
content = docToHtml(inputStream, sourceFileName);
} else if (sourceFileName.endsWith(".docx")) {
content = docxToHtml(inputStream, sourceFileName);
} else {
return "文件类型错误";
}
// 利用正则表达式过滤无用标签和属性
// content = RegexAnswerUtil.clear(content);
return content;
} /**
* 将doc文件转变为html
*
* @param fileInputStream
* @param sourceFileName
* @return
* @throws Exception
*/
public static String docToHtml(InputStream fileInputStream, String sourceFileName) throws Exception {
String targetFileName = imagePathStr + sourceFileName.substring(0, sourceFileName.lastIndexOf(".")) + ".html";
HWPFDocument wordDocument = new HWPFDocument(fileInputStream);
Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
WordToHtmlConverter wordToHtmlConverter = new WordToHtmlConverter(document);
// 保存图片,并返回图片的相对路径
wordToHtmlConverter.setPicturesManager(new PicturesManager() {
@Override
public String savePicture(byte[] content, PictureType pictureType, String name, float width, float height) {
name = getTimeUUID() + name;
try (FileOutputStream out = new FileOutputStream(new File(imagePathStr + name))) {
out.write(content);
} catch (Exception e) {
e.printStackTrace();
}
return imagePath + "\\" + name;
}
}); /*wordToHtmlConverter.setPicturesManager((content, pictureType, name, width, height) -> {
// name = DateUtil.getTimeString() + name;
name = getTimeUUID() + name;
try (FileOutputStream out = new FileOutputStream(new File(imagePathStr + name))) {
out.write(content);
} catch (Exception e) {
e.printStackTrace();
}
return imagePath + "\\" + name;
});*/
wordToHtmlConverter.processDocument(wordDocument);
Document htmlDocument = wordToHtmlConverter.getDocument();
DOMSource domSource = new DOMSource(htmlDocument);
StreamResult streamResult = new StreamResult(new File(targetFileName));
TransformerFactory tf = TransformerFactory.newInstance();
Transformer serializer = tf.newTransformer();
serializer.setOutputProperty(OutputKeys.ENCODING, "utf-8");
serializer.setOutputProperty(OutputKeys.INDENT, "yes");
serializer.setOutputProperty(OutputKeys.METHOD, "html");
serializer.transform(domSource, streamResult);
String content = splitContext(targetFileName);
// 删除生成的html文件
File file = new File(targetFileName);
// file.delete();
System.out.println("content= " + content);
return content;
} /**
* docx转换为html
*
* @param inputStream
* @param sourceFileName
* @return
* @throws Exception
*/
public static String docxToHtml(InputStream inputStream, String sourceFileName) throws Exception {
String targetFileName = imagePathStr + sourceFileName.substring(0, sourceFileName.lastIndexOf(".")) + ".html";
File target = new File(targetFileName);
target.getParentFile().mkdirs();
OutputStreamWriter outputStreamWriter = null;
try {
XWPFDocument document = new XWPFDocument(inputStream);
XHTMLOptions options = XHTMLOptions.create();
// 存放图片的文件夹
options.setExtractor(new FileImageExtractor(new File(imagePathStr)));
// html中图片的路径
options.URIResolver(new BasicURIResolver(imagePath));
outputStreamWriter = new OutputStreamWriter(new FileOutputStream(target), "utf-8");
XHTMLConverter xhtmlConverter = (XHTMLConverter) XHTMLConverter.getInstance();
xhtmlConverter.convert(document, outputStreamWriter, options);
} finally {
if (outputStreamWriter != null) {
outputStreamWriter.close();
}
}
String content = splitContext(targetFileName);
// 删除生成的html文件
File file = new File(targetFileName);
file.delete();
// System.out.println(" content docx= " + content);
return content;
} /**
* 读取转换得到的html文件,并过滤多余空行
*/
public static String splitContext(String filePath) {
File file = new File(filePath);
BufferedReader reader = null;
try {
InputStreamReader isr = new InputStreamReader(new FileInputStream(file), "UTF-8");
reader = new BufferedReader(isr);
StringBuilder sb = new StringBuilder();
String tempString = null;
// 一次读入一行,直到读入null为文件结束
while ((tempString = reader.readLine()) != null) {
sb.append(tempString);
if (!"".equals(tempString)) {
sb.append("\n");
}
}
reader.close();
String content = sb.toString().replaceAll("\\n+", "\n");
return content;
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e1) {
}
}
}
return "";
}
}
5.测试
5.1.页面效果
5.2.点击导入按钮
5.3.导入成功提示
注意:本文中主要讲解上传流程和逻辑,实际生产中需要根据产品要求给出友好提示,如文件类型限制,上传前提醒用户使用上传该文件等友好提示
完美!