java导出word,我们一般会选用dom4j,dom4j有点很多,最大的有点就是免费。但是dom4j处理插入图片这块的代码实在是难懂,并且网上的资料非常难找。
经过多方研究,于是就找到了Spire.doc,它非常优秀,处理doc文件api清晰,基本上就是一步到位.
我这边的导出是采用书签替换的方式,先在word模板中的各个指定位置创建书签。
然后在使用Spire对书签进行替换.
@Slf4j
@Api(value = "导出报表", tags = { "导出报表" })
@RestController
@RequestMapping("/word")
public class PrintController
{
public static final String BASE_FILE = "bbword/";//wordbase路径
public static final String WRITTEN_COMMENTS = NotionItem.NotionKind.Text;//常量文字意见
public static final String PICTURE_COMMENTS = NotionItem.NotionKind.WritePad;//常量手绘板意见
@Resource
private NotionService m_NotionService;
@Value("${hcit.imagenotion}")
private String imageNotionBasePath;
@GetMapping("/down")
public void down(HttpServletResponse P_Response, HttpServletRequest P_Request) throws Exception
{
//设置Http的Header
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
//模板附件位置
//增加所属机构的选择条件
String strWordPath = "";
String strTemplatePath = AppConfig.getUploadPath();
//报表地址生成后在服务器上的位置
String strDestPath = strTemplatePath + BASE_FILE;
File file = new File(strDestPath);
if (file.exists() == false)
{
file.mkdirs();
}
String strFileType = "docx";
String strNewDocxUnid = HCSystem.newUnid().toString();
String strNewDocxPath = strNewDocxUnid + strFileType;
strDestPath = strTemplatePath + BASE_FILE + strNewDocxPath;//生成的新的文件的路径
String strSourceFilePath = "模板文件的路径";//获取附件保存路径
com.spire.doc.Document doc1 = new com.spire.doc.Document();
doc1.loadFromStream(new FileInputStream(strSourceFilePath), FileFormat.Docx);
String strValue = "对应的书签值";
BookmarksNavigator bookmarksNavigator = new BookmarksNavigator(doc1);
bookmarksNavigator.moveToBookmark("书签名称");//这个相当于把位置移动到书签的位置
bookmarksNavigator.replaceBookmarkContent(strValue, true);//书签处替换成书签值
StringBuffer preTypeBuf = new StringBuffer();//这里是插入多断文字的方法
if (WRITTEN_COMMENTS.equals(""))//这个if里面是处理多行文本
{
if (preTypeBuf.length() > 0)
{
preTypeBuf.append("\n");//doc中的换行用\n表示
}
// 替换掉书签中阅文意见部分的内容
BookmarksNavigator bookmarksNavigatorYwyj = new BookmarksNavigator(doc1);
preTypeBuf.append("\n");
bookmarksNavigatorYwyj.moveToBookmark("书签名",true,false);//这是移动到书签的最后位置,循环遍历插入同一个书签时用这个方法
bookmarksNavigatorYwyj.insertText(preTypeBuf.toString(),true);//在书签的末尾插入文本,这个个方法不会替换掉书签
}
else if(PICTURE_COMMENTS.equals(""))
{
//这里是处理图片
//如果你跟我一样是要处理签名图片时,这里要插入落款署名时,要先插入.单纯的处理图片,下面三行代码就不用要了.
BookmarksNavigator bookmarksNavigatorLk = new BookmarksNavigator(doc1);
bookmarksNavigatorLk.moveToBookmark("书签名",true,true);
bookmarksNavigatorLk.insertText(preTypeBuf.toString(),true);
// 替换掉书签中阅文意见部分的内容
BookmarksNavigator bookmarksNavigatorImg = new BookmarksNavigator(doc1);
bookmarksNavigatorImg.moveToBookmark("书签名",true,true);
Paragraph para = new Paragraph(doc1);
String filePath = this.imageNotionBasePath + "fileName";
String newfilePath = this.imageNotionBasePath + "newfileName";
File newFile = new File(newfilePath);
if(newFile.exists())
{
//文件如果存在就不用再次处理了
}
else
{
ImgCropp.ImgCropping(filePath,newfilePath);//先自动裁剪调多余的部分,因为我这边的业务是用户使用外设签名,所以生成的图片有很大一部分空白.如果你的没有,就不用了
newFile = new File(newfilePath);
if(newFile.exists())
{
//文件存在
}
else
{
//转换失败了,还用原图,如果文件是纯白色,或者什么都没有的空文件,裁剪会失败.
newfilePath = filePath;
}
}
log.info(newfilePath);
DocPicture picture = para.appendPicture(newfilePath);
float width = picture.getWidth();
float height = picture.getHeight();
if(width > 300)//设置最大宽度300
{
//需要缩放
float bl = 300/width;
width = 300f;
//计算比例
height = height * bl;
}
if (height > 200)//最大高度200
{
//需要缩放
float bl = 200/height;
height = 200f;
//计算比例
width = width * bl;
}
//计算一下图片的缩放比例,最大不能超过
picture.setWidth(width);//设置图片的宽度
picture.setHeight(height);//设置图片的高度
picture.setTextWrappingStyle(TextWrappingStyle.Inline);//嵌入式,建议使用嵌入式插入,会随着文本的编辑随动
picture.setTextWrappingType(TextWrappingType.Both);
bookmarksNavigatorImg.insertParagraph(para);//插入图片,同样,这个操作不会替换掉书签,适用于遍历插入时.
}
doc1.protect(ProtectionType.Allow_Only_Reading, "aksjdjag");//这里是把书签设置为只读
doc1.saveToFile(strDestPath, FileFormat.Docx);//处理完以后,把文件保存到指定的位置.
doc1.dispose();
String strFileName = "文件标题";
strFileName = FileUtils.setFileDownloadHeader(P_Request, strFileName);
P_Response.setHeader("Access-Control-Expose-Headers", "Content-Disposition,Content-Type");
P_Response.setHeader("Content-Disposition", "attachment;filename=" + strFileName);
P_Response.setHeader("Content-Type", "application/word");
FileUtils.writeBytes(strWordPath, P_Response.getOutputStream());//输出到前端.
}
}
以上代码是经过我整理的,适用于我这边业务的代码,其中有关于图片的裁剪的方法,看我的另一个文章.