您的位置:首页 > 编程语言 > Java开发

javaUtil---导出数据到word表格中后,下载word文档

2017-11-29 16:08 399 查看
为满足将对应数据插入到word表格中并导出word模板,下载word模板。

utils的 controller里的方法:

1.利用ResponseEntity 实体进行文件导出,以解决导出文件名称自定,防止乱码的效果。因为 ResponseEntity 可以对http协议的header进行设定来设定编码格式。

public static final String TargetDir = "targetfile" + File.separator;
public static final String DownloadDir = "downloadfile" + File.separator;
public static ResponseEntity<byte[]> fileDownload(File targetfile,
String filename, HttpServletRequest request) {
try {
if (targetfile.exists() && targetfile.isFile()) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);//设置header的contenttype为字节流。
String userAgent = request.getHeader("User-Agent");//通过userAgent判断浏览器类型
byte[] bytes = userAgent.contains("MSIE") ? filename.getBytes()
: filename.getBytes("UTF-8"); // name.getBytes("UTF-8")处理safari的乱码问题,解决文件名乱码问题
String fileName = new String(bytes, "ISO-8859-1");
headers.set(HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename=\"" + fileName + "\"");//设置CONTENT_DISPOSITION使浏览器打开文件下载对话框

byte[] readFileToByteArray = null;
readFileToByteArray = FileUtils.readFileToByteArray(targetfile);
return new ResponseEntity<byte[]>(readFileToByteArray, headers,
HttpStatus.OK);
}
} catch (IOException e) {
e.printStackTrace();
}
return new ResponseEntity<byte[]>(HttpStatus.INTERNAL_SERVER_ERROR)
}


2.获取模板文件路径

//params是一个数据map集合,此数据集合用于将数据插入对应模板的对应位置。然后利用XWPFDocument相关技术操作word文档。

public static String getDocxPath(HttpServletRequest request, String type,
Map<String, String> params) {
Map<String, Object> params1 = new HashMap<String, Object>();

for (Entry<String, String> entry : params.entrySet()) {
params1.put(entry.getKey(), entry.getValue());
}

return getDocxPathIncludePic(request, type, params1);
}
public static String getDocxPathIncludePic(HttpServletRequest request,
String type, Map<String, Object> params) {

Map<String, String> docxMapping = SpringContextHolder
.getBean("docxMapping");
String fileTargetPath = docxMapping.get(type);//此tape为配置文件里的key值。通过key值获得对应模板的名字
String tf = null;
if (fileTargetPath != null) {
File dir = new File(request.getSession().getServletContext()
.getRealPath("/")
+ DownloadDir + UserUtils.getUser().getId());//替换后文件暂存文件夹
if (!dir.exists())
dir.mkdirs(); // 如果目标文件夹不存在则创建新的文件夹
InputStream is = null;
OutputStream os = null;

try {
is = new FileInputStream(request.getSession()
.getServletContext().getRealPath("/")
+ TargetDir + fileTargetPath);//获取模板word文件地址
XWPFDocument doc = new XWPFDocument(is);
replaceInTable(doc, params, "");//调用函数替换word文档中的内容
tf = dir.getPath()
+ File.separator
+ UUID.randomUUID().toString().replace("-", "")
.concat(".docx");
os = new FileOutputStream(tf);
doc.write(os);//生成新的word文件

} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (os != null) {
os.close();
}
if (is != null) {
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
return tf;
}


3.context配置文件中设置docxMapping bean

<bean id="docxMapping" class="java.util.HashMap">
<constructor-arg>
<map>
<entry>
<key>
<value><![CDATA[test]]></value>
</key>
<value><![CDATA[test.docx]]></value>
</entry>
</map>
</constructor-arg>
</bean>


4.替换word模板内容的方法

private static void replaceInTable(XWPFDocument doc,
Map<String, Object> params, String destFilePath) {
Iterator<XWPFTable> iterator = doc.getTablesIterator();//获取word文档中的表格集合
XWPFTable table;
List<XWPFTableRow> rows;
List<XWPFTableCell> cells;
List<XWPFParagraph> paras;
while (iterator.hasNext()) {
table = iterator.next();
rows = table.getRows();
for (XWPFTableRow row : rows) {
cells = row.getTableCells();
for (XWPFTableCell cell : cells) {
paras = cell.getParagraphs();//获取单元格中的段落
for (XWPFParagraph para : paras) {
replaceInPara(para, params, destFilePath, doc, cell);//调用方法替换单元格内的一个段落
}
}
}
}
Iterator<XWPFParagraph> itPara = doc.getParagraphsIterator();
XWPFParagraph paragraph;
while (itPara.hasNext()) {
paragraph = (XWPFParagraph) itPara.next();
replaceInPara(paragraph, params, destFilePath, doc, null);
}
}


4.替换单元格内的数据方法

替换原理:在模板文件中需要填写内容的单元格写一些key,通过传入map的key与模板中的key对应,将单元格中的key替换成应该填入的内容。

private static void replaceInPara(XWPFParagraph para,
Map<String, Object> params, String destFilePath, XWPFDocument doc,
XWPFTableCell cell) {
List<XWPFRun> runs = para.getRuns();//获取段落中的文字
for (int i = 0; i < runs.size(); i++) {
XWPFRun run = runs.get(i);
String runText = run.toString();
for (Map.Entry<String, Object> entry : params.entrySet()) {
String key = entry.getKey();
if (key.equals(runText.trim())) {
Object value = entry.getValue();
if (value == null) {
para.removeRun(i);
}
// 文本替换
else if (value instanceof String) {
String ff = run.getFontFamily();
int fs = run.getFontSize();
para.removeRun(i);
XWPFRun newrun = para.insertNewRun(i);
newrun.setText(value.toString());
newrun.setFontFamily(ff);
newrun.setFontSize(fs);
}
// 图片替换
else if (value instanceof Map) {
para.removeRun(i);
XWPFRun newrun = para.insertNewRun(i);
Map<String, Object> pic = (Map<String, Object>) value;
// byte[] byteArray = (byte[]) pic.get("content");
// ByteArrayInputStream byteInputStream = new
// ByteArrayInputStream(
// byteArray);
if (pic != null) {
try {
createPicture(doc, newrun, pic, para);
} catch (Exception e) {
e.printStackTrace();
}
}
}
} else {
continue;
}
}
}
}


5.辅助方法:

/**
* 将输入流中的数据写入字节数组
*
* @param in
* @return
*/
public static byte[] inputStream2ByteArray(InputStream in, boolean isClose) {
byte[] byteArray = null;
try {
int total = in.available();
byteArray = new byte[total];
in.read(byteArray);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (isClose) {
try {
in.close();
} catch (Exception e2) {
e2.printStackTrace();
}
}
}
return byteArray;
}

/**
* 根据图片类型,取得对应的图片类型代码
*
* @param picType
* @return int
*/
private static int getPictureType(String picType) {
int res = XWPFDocument.PICTURE_TYPE_PICT;
if (picType != null) {
if (picType.equalsIgnoreCase("png")) {
res = XWPFDocument.PICTURE_TYPE_PNG;
} else if (picType.equalsIgnoreCase("dib")) {
res = XWPFDocument.PICTURE_TYPE_DIB;
} else if (picType.equalsIgnoreCase("emf")) {
res = XWPFDocument.PICTURE_TYPE_EMF;
} else if (picType.equalsIgnoreCase("jpg")
|| picType.equalsIgnoreCase("jpeg")) {
res = XWPFDocument.PICTURE_TYPE_JPEG;
} else if (picType.equalsIgnoreCase("wmf")) {
res = XWPFDocument.PICTURE_TYPE_WMF;
}
}
return res;
}

/**
* 获取图片的param参数
*
* @param width
*            宽度
* @param height
*            高度
* @param imgType
*            图片类型 现在只支持 png,dib,emf,jpg,jpeg,wmf
* @param fileUrl
*            文件url路径
* @return
*/
public static Map<String, Object> getPictureParam(int width, int height,
String imgType, String fileUrl) {
Map<String, Object> header = new HashMap<String, Object>();
header.put("width", width);
header.put("height", height);
header.put("type", imgType);
header.put("fileUrl", fileUrl);
// try {
// header.put("content",
// inputStream2ByteArray(new FileInputStream(fileUrl), true));
// } catch (FileNotFoundException e) {
// e.printStackTrace();
// }
return header;
}

/**
* @param id
* @param width
*            宽
* @param height
*            高
* @param paragraph
*            段落
*/
private static void createPicture(XWPFDocument doc, XWPFRun run,
Map<String, Object> pic, XWPFParagraph paragraph) {
FileInputStream fileInputStream = null;
int width = Integer.parseInt(pic.get("width").toString());
int height = Integer.parseInt(pic.get("height").toString());
int picType = getPictureType(pic.get("type").toString());
String fileUrl = pic.get("fileUrl").toString();
int id = 0;
try {
id = doc.getNextPicNameNumber(picType);
} catch (InvalidFormatException e1) {
e1.printStackTrace();
}

try {
fileInputStream = new FileInputStream(fileUrl);
final String blipId = run.getDocument().addPictureData(
fileInputStream, picType);

final int EMU = 9525;
width *= EMU;
height *= EMU;
// String blipId =
// getAllPictures().get(id).getPackageRelationship().getId();

final CTInline inline = run.getCTR().addNewDrawing().addNewInline();

final String picXml = ""
+ "<a:graphic xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\">"
+ "   <a:graphicData uri=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">"
+ "      <pic:pic xmlns:pic=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">"
+ "         <pic:nvPicPr>" + "            <pic:cNvPr id=\""
+ id
+ "\" name=\"Generated\"/>"
+ "            <pic:cNvPicPr/>"
+ "         </pic:nvPicPr>"
+ "         <pic:blipFill>"
+ "            <a:blip r:embed=\""
+ blipId
+ "\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\"/>"
+ "            <a:stretch>"
+ "               <a:fillRect/>"
+ "            </a:stretch>"
+ "         </pic:blipFill>"
+ "         <pic:spPr>"
+ "            <a:xfrm>"
+ "               <a:off x=\"0\" y=\"0\"/>"
+ "               <a:ext cx=\""
+ width
+ "\" cy=\""
+ height
+ "\"/>"
+ "            </a:xfrm>"
+ "            <a:prstGeom prst=\"rect\">"
+ "               <a:avLst/>"
+ "            </a:prstGeom>"
+ "         </pic:spPr>"
+ "      </pic:pic>"
+ "   </a:graphicData>" + "</a:graphic>";

// CTGraphicalObjectData graphicData =
// inline.addNewGraphic().addNewGraphicData();
XmlToken xmlToken = null;
xmlToken = XmlToken.Factory.parse(picXml);
inline.set(xmlToken);
// graphicData.set(xmlToken);

inline.setDistT(0);
inline.setDistB(0);
inline.setDistL(0);
inline.setDistR(0);

final CTPositiveSize2D extent = inline.addNewExtent();
extent.setCx(width);
extent.setCy(height);

final CTNonVisualDrawingProps docPr = inline.addNewDocPr();
docPr.setId(id);
docPr.setName("Picture " + id);
docPr.setDescr("Generated");
} catch (final Exception e) {
run.setText("图片路径有误或者非标准格式图片,请到网站下载自行插入");
run.setColor("FF0000");
} finally {
// close streams
if (fileInputStream != null) {
try {
fileInputStream.close();
} catch (final IOException ioEx) {
// can be ignored
}
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: