javaUtil---匯出資料到word表格中後,下載word文件
阿新 • • 發佈:2019-01-24
為滿足將對應資料插入到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
}
}
}
}