之前在工作中做了一个法院文书模板的文首文尾合并工具,这里把部分功能代码片段记录下来,方便后续使用
- 1. 通过swagger接口上传文件报错,设置servlet支持上传文件大小。(不加单位是Byte,可用单位Mb)
- 2. 遍历文件夹下的所有文件,如果是文件夹,就在另一个目录下新建一个相同的文件夹(递归复制文件夹使用,因为后面复制文件时并不会自动创建文件夹),并且递归遍历,如果是文件就把文件名和文件路径存储到map中,因为不同目录中可能会有相同文件名的文件,所以只能用允许key值重复的map → IdentityHashMap。
- 3. POI删除word中从书签A到书签B中间的所有内容
- 4. POI复制段落,从paragraphA到paragraphB
- 5. 上传的文件解压到指定路径
- 6. 递归压缩文件夹
- 7. 递归删除文件夹方法
- 8. 主功能
- 9. Controller使用swagger页面上传下载文件
1. 通过swagger接口上传文件报错,设置servlet支持上传文件大小。(不加单位是Byte,可用单位Mb)
# 单个文件的最大值
spring.servlet.multipart.max-file-size=1000000000
# 上传文件总的最大值
spring.servlet.multipart.max-request-size=1000000000
2. 遍历文件夹下的所有文件,如果是文件夹,就在另一个目录下新建一个相同的文件夹(递归复制文件夹使用,因为后面复制文件时并不会自动创建文件夹),并且递归遍历,如果是文件就把文件名和文件路径存储到map中,因为不同目录中可能会有相同文件名的文件,所以只能用允许key值重复的map → IdentityHashMap。
IdentityHashMap hbFiles = new IdentityHashMap();
Map<String, String> hbMap = dealFile(hbFiles, path + File.separator + dirNameSource, dirNameSource);
public static Map<String, String> dealFile(Map files, String filePath, String dirNameSource) {
File file = new File(filePath);
String[] fileNameLists = file.list();
File[] filePathLists = file.listFiles();
for (int i = 0; i < filePathLists.length; i++) {
if (filePathLists[i].isFile()) {
String path = filePathLists[i].getPath();
//把文件名作为key,文件路径为value 存储在map中
files.put(fileNameLists[i], path);
} else {
(new File(filePathLists[i].getPath().replace("mergeTpl" + File.separator + dirNameSource, "ext"))).mkdirs();
dealFile(files, filePathLists[i].getPath(), dirNameSource);
}
}
return files;
}
3. POI删除word中从书签A到书签B中间的所有内容
public static int delete(XWPFDocument document, String startBookmark, String endBookmark) {
List<XWPFParagraph> paragraphs = document.getParagraphs();
int start = 0;
int end = 0;
for (XWPFParagraph paragraph : paragraphs) {
List<CTBookmark> bookmarkStartList = paragraph.getCTP().getBookmarkStartList();
for (CTBookmark bookmark : bookmarkStartList) {
if (bookmark.getName().equals(startBookmark)) {
start = paragraphs.indexOf(paragraph);
}
if (bookmark.getName().equals(endBookmark)) {
end = paragraphs.indexOf(paragraph);
}
}
}
for (int i = end; i > start; i--) {
document.removeBodyElement(i);
}
return start;
}
4. POI复制段落,从paragraphA到paragraphB
/**
* 功能描述:复制段落,从source到target
*/
public static void copyParagraph(XWPFParagraph target,
XWPFParagraph source, Integer index) {
// 设置段落样式
target.getCTP().setPPr(source.getCTP().getPPr());
// 移除所有的run
for (int pos = target.getRuns().size() - 1; pos >= 0; pos--) {
target.removeRun(pos);
}
// copy 新的run
for (XWPFRun s : source.getRuns()) {
XWPFRun targetrun = target.createRun();
copyRun(targetrun, s, index);
}
CTBookmark ctBookmark = target.getCTP().addNewBookmarkStart();
ctBookmark.setId(BigInteger.valueOf(100000001));
//书签名称
ctBookmark.setName("permEnd0");
target.createRun();
target.getCTP().addNewBookmarkEnd().setId(BigInteger.valueOf(100000001));
}
/**
* 功能描述:复制RUN,从source到target
*/
public static void copyRun(XWPFRun target, XWPFRun source, Integer
index) {
// 设置run属性
target.getCTR().setRPr(source.getCTR().getRPr());
// 设置文本
String tail = "";
if (index != null) {
tail = index.toString();
}
target.setText(source.text());
}
5. 上传的文件解压到指定路径
/**
* 解压zip格式的压缩文件到指定位置
*
* @param zipFileName 压缩文件
* @param extPlace 解压目录
* @throws Exception
*/
public static boolean unZipFiles(MultipartFile zipFileName, String extPlace) {
System.setProperty("sun.zip.encoding",
System.getProperty("sun.jnu.encoding"));
try {
(new File(extPlace)).mkdirs();
File f = new File(zipFileName.getOriginalFilename());
FileUtils.copyInputStreamToFile(zipFileName.getInputStream(), f);
ZipFile zipFile = new ZipFile(f, "GBK"); // 处理中文文件名乱码的问题
if ((!f.exists()) && (f.length() <= 0)) {
throw new Exception("要解压的文件不存在!");
}
String strPath, gbkPath, strtemp;
File tempFile = new File(extPlace);
strPath = tempFile.getAbsolutePath();
Enumeration<?> e = zipFile.getEntries();
while (e.hasMoreElements()) {
org.apache.tools.zip.ZipEntry zipEnt = (org.apache.tools.zip.ZipEntry) e.nextElement();
gbkPath = zipEnt.getName();
if (zipEnt.isDirectory()) {
strtemp = strPath + File.separator + gbkPath;
File dir = new File(strtemp);
dir.mkdirs();
continue;
} else { // 读写文件
InputStream is = zipFile.getInputStream(zipEnt);
BufferedInputStream bis = new BufferedInputStream(is);
gbkPath = zipEnt.getName();
strtemp = strPath + File.separator + gbkPath;// 建目录
String strsubdir = gbkPath;
for (int i = 0; i < strsubdir.length(); i++) {
if (strsubdir.substring(i, i + 1).equalsIgnoreCase("/")) {
String temp = strPath + File.separator
+ strsubdir.substring(0, i);
File subdir = new File(temp);
if (!subdir.exists()) {
subdir.mkdir();
}
}
}
FileOutputStream fos = new FileOutputStream(strtemp);
BufferedOutputStream bos = new BufferedOutputStream(fos);
int c;
while ((c = bis.read()) != -1) {
bos.write((byte) c);
}
bos.close();
fos.close();
is.close();
bis.close();
}
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
6. 递归压缩文件夹
private static final int BUFFER_SIZE = 2 * 1024;
/**
* 压缩成ZIP 方法
*
* @param srcDir 压缩文件夹路径
* @param out 压缩文件输出流
* @param KeepDirStructure 是否保留原来的目录结构,true:保留目录结构;
* <p>
* false:所有文件跑到压缩包根目录下(注意:不保留目录结构可能会出现同名文件,会压缩失败)
* @throws RuntimeException 压缩失败会抛出运行时异常
*/
public static void toZip(String srcDir, OutputStream out, boolean KeepDirStructure) throws RuntimeException {
long start = System.currentTimeMillis();
ZipOutputStream zos = null;
try {
zos = new ZipOutputStream(out);
File sourceFile = new File(srcDir);
compress(sourceFile, zos, sourceFile.getName(), KeepDirStructure);
long end = System.currentTimeMillis();
System.out.println("压缩完成,耗时:" + (end - start) + " ms");
} catch (Exception e) {
throw new RuntimeException("zip error from ZipUtils", e);
} finally {
if (zos != null) {
try {
zos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 递归压缩方法
*
* @param sourceFile 源文件
* @param zos zip输出流
* @param name 压缩后的名称
* @param KeepDirStructure 是否保留原来的目录结构, true:保留目录结构;
* false:所有文件跑到压缩包根目录下(注意:不保留目录结构可能会出现同名文件,会压缩失败)
* @throws Exception
*/
private static void compress(File sourceFile, ZipOutputStream zos, String name, boolean KeepDirStructure)
throws Exception {
byte[] buf = new byte[BUFFER_SIZE];
if (sourceFile.isFile()) {
// 向zip输出流中添加一个zip实体,构造器中name为zip实体的文件的名字
zos.putNextEntry(new ZipEntry(name));
// copy文件到zip输出流中
int len;
FileInputStream in = new FileInputStream(sourceFile);
while ((len = in.read(buf)) != -1) {
zos.write(buf, 0, len);
}
// Complete the entry
zos.closeEntry();
in.close();
} else {
File[] listFiles = sourceFile.listFiles();
if (listFiles == null || listFiles.length == 0) {
// 需要保留原来的文件结构时,需要对空文件夹进行处理
if (KeepDirStructure) {
// 空文件夹的处理
zos.putNextEntry(new ZipEntry(name + "/"));
// 没有文件,不需要文件的copy
zos.closeEntry();
}
} else {
for (File file : listFiles) {
// 判断是否需要保留原来的文件结构
if (KeepDirStructure) {
// 注意:file.getName()前面需要带上父文件夹的名字加一斜杠,
// 不然最后压缩包中就不能保留原来的文件结构,即:所有文件都跑到压缩包根目录下了
compress(file, zos, name + "/" + file.getName(), KeepDirStructure);
} else {
compress(file, zos, file.getName(), KeepDirStructure);
}
}
}
}
}
7. 递归删除文件夹方法
public static void delete(File file) {
//判断文件不为null或文件目录存在
if (file == null || !file.exists()) {
return;
}
//取得这个目录下的所有子文件对象
File[] files = file.listFiles();
//遍历该目录下的文件对象
for (File f : files) {
//判断子目录是否存在子目录,如果是文件则删除
if (f.isDirectory()) {
delete(f);
} else {
f.delete();
}
}
//删除空文件夹 for循环已经把上一层节点的目录清空。
file.delete();
}
8. 主功能
public static void dealTplFile(String path, String startTag, String endTag, String dirNameSource, String dirNameTarget) {
(new File(path.replace("mergeTpl", "ext"))).mkdirs();
IdentityHashMap hbFiles = new IdentityHashMap();
Map<String, String> hbMap = dealFile(hbFiles, path + File.separator + dirNameSource, dirNameSource);
for (Map.Entry<String, String> entry : hbMap.entrySet()) {
String TplName = entry.getKey();
String hbTplPath = entry.getValue();
String hnTplPath = hbTplPath.replace(dirNameSource, dirNameTarget);
if (!new File(hnTplPath).exists()) {
logger.error("未找到【" + dirNameTarget + "】目录下的文件:" + TplName);
continue;
}
OutputStream os = null;
try {
XWPFDocument source = new XWPFDocument(new FileInputStream(hbTplPath));
XWPFDocument target = new XWPFDocument(new FileInputStream(hnTplPath));
XWPFDocument document = mergeWord(source, target, startTag, endTag);
os = new FileOutputStream(hbTplPath.replace("mergeTpl" + File.separator + dirNameSource, "ext"));
document.write(os);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
public static XWPFDocument mergeWord(XWPFDocument source, XWPFDocument target, String startTag, String endTag) {
int delete = delete(target, "permStart0", "permEnd0");
boolean startCopy = false;
for (XWPFParagraph s_paragraph : source.getParagraphs()) {
if (s_paragraph.getText().contains(endTag)) {
break;
}
if (startCopy == true) {
XmlCursor xmlCursor = target.getParagraphs().get(delete).getCTP().newCursor();
xmlCursor.toNextSibling();
target.insertNewParagraph(xmlCursor);
delete++;
copyParagraph(target.getParagraphArray(delete), s_paragraph, 0);
}
if (s_paragraph.getText().contains(startTag)) {
while (target.getParagraphs().get(delete).getRuns().size() != 0) {
target.getParagraphs().get(delete).removeRun(0);
}
for (XWPFRun run : s_paragraph.getRuns()) {
XWPFRun run1 = target.getParagraphs().get(delete).createRun();
copyRun(run1, run, 0);
}
startCopy = true;
}
}
return target;
}
9. Controller使用swagger页面上传下载文件
@RestController
@RequestMapping("/mergeTpl")
@Api(value = "文件controller", tags = {"A - 模板合并工具"})
public class MergeTplController {
@ResponseBody
@PostMapping(value = "/upload", consumes = "multipart/*", headers = "content-type=multipart/form-data")
@ApiOperation(value = "上传模板包")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "上传成功!"),
@ApiResponse(code = 500, message = "上传失败!")
})
public ResponseEntity mergeTpl(@ApiParam(value = "模板包", required = true) MultipartFile file,
@RequestParam(required = false, defaultValue = "【案号】") String startTag,
@RequestParam(required = false, defaultValue = "【审判人员】") String endTag,
@RequestParam(required = false, defaultValue = "海南") String dirNameTarget,
@RequestParam(required = false, defaultValue = "行业标准") String dirNameSource) throws IOException {
String jypath = System.getProperty("user.dir") + File.separator + "merge" + File.separator + "mergeTpl";
String outputpath = System.getProperty("user.dir") + File.separator + "merge" + File.separator + "ext";
String mainpath = System.getProperty("user.dir") + File.separator + "merge";
MergeTplUtil.unZipFiles(file, jypath);
MergeTplUtil.dealTplFile(jypath, startTag, endTag, dirNameSource, dirNameTarget);
OutputStream ops = new FileOutputStream(new File(mainpath + File.separator + "ext.zip"));
MergeTplUtil.toZip(outputpath, ops, true);
InputStream is = new FileInputStream(mainpath + File.separator + "ext.zip");
String fileName = "合并后文件.zip";
MergeTplUtil.delete(new File(mainpath));
File copyfile = new File(System.getProperty("user.dir") + file.getName());
if (copyfile.exists()) {
copyfile.delete();
}
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
return new ResponseEntity(IOUtils.toByteArray(is), headers, HttpStatus.OK);
}
}