Generating Word Documents in Spring Boot with POI-TL and Previewing in Vue via vue-office
Backend: Java Service Integration
Add the POI-TL library to your Maven pom.xml:
<dependency>
<groupId>com.deepoove</groupId>
<artifactId>poi-tl</artifactId>
<version>1.7.3</version>
</dependency>
Create a placeholder-based Word template (.docx) and place it under the resources/templates directory, for example payment_cover.docx.
Implement a service method that populates the template and streams it to the HTTP response:
import com.deepoove.poi.XWPFTemplate;
import org.springframework.core.io.ClassPathResource;
// inside a controller or service
public void exportPaymentCover(HttpServletResponse response) throws Exception {
String templateLocation = "templates/payment_cover.docx";
ClassPathResource resource = new ClassPathResource(templateLocation);
Map<String, Object> data = new HashMap<>();
data.put("contractor", "Acme Construction Co.");
data.put("paymentPhase", "Phase II - North Zone");
data.put("preparedBy", "Global Supplies Ltd.");
data.put("siteOffice", "SafeBuild Engineering Consultants");
data.put("headOffice", "Highway Project Management Co.");
data.put("date", "2024-08-15");
response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
response.setHeader("Content-Disposition", "attachment; filename=payment_cover.docx");
try (InputStream templateStream = resource.getInputStream();
OutputStream out = response.getOutputStream()) {
XWPFTemplate template = XWPFTemplate.compile(templateStream).render(data);
template.write(out);
out.flush();
}
}
Frontend: Vue Integration
Install the @vue-office/docx package:
npm install --save @vue-office/docx
dispatch the output as a Blob from the backend API call, convert it to an object URL, and04 render it with the <vue-office-docx> component.
Template section:
<template>
<div>
<vue-office-docx
v-if="documentUrl"
:src="documentUrl"
@rendered="handleRendered"
id="docPreview"
/>
<button @click="printDocument">Print</button>
<button @click="downloadDocument">Download</button>
</div>
</template>
Script setup:
import { ref } from 'vue';
import VueOfficeDocx from '@vue-office/docx';
import '@vue-office/docx/lib/index.css';
import { saveAs } from 'file-saver';
export default {
components: { VueOfficeDocx },
setup() {
const documentUrl = ref(null);
const blobData = ref(null);
const fileName = ref('document.docx');
// Simulated fetch: replace with real API call
const fetchDocument = async () => {
const response = await fetch('/api/export/paymentCover');
const arrayBuffer = await response.arrayBuffer();
const blob = new Blob([arrayBuffer], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
blobData.value = blob;
documentUrl.value = window.URL.createObjectURL(blob);
};
const handleRendered = () => {
console.log('Document preview rendered successfully');
};
const printDocument = () => {
const container = document.getElementById('docPreview');
if (container) {
const wrapper = container.querySelector('.docx-wrapper');
if (wrapper) {
// optional: use a print plugin, e.g., vue-print-nb
this.$print(wrapper);
}
}
};
const downloadDocument = () => {
if (blobData.value) {
saveAs(blobData.value, fileName.value);
}
};
return {
documentUrl,
handleRendered,
printDocument,
downloadDocument,
fetchDocument
};
},
mounted() {
this.fetchDocument();
}
};
The vue-office-docx component handles rendering the docx file directly in the browser. The blob URL is passed as the src prop. After the document is rendered, you can integrate print functionality by targeting the internal wrapper element.