How to Seamlessly Integrate OnlyOffice with Spring Boot for Online Word Editing and Saving
This guide walks through deploying OnlyOffice, wiring a Vue front‑end with Element UI, implementing Spring Boot back‑end endpoints to load, edit, and save Word documents, handling token verification, and troubleshooting common deployment and configuration issues.
Introduction
A recent project required a web page that could edit Word documents online and persist the changes. The open‑source OnlyOffice suite provides document conversion, collaborative editing, and printing, but only the document‑editing feature was needed.
1. OnlyOffice Deployment
OnlyOffice can be deployed either via Docker (pull the image and start with a config file) or by installing directly on a Linux host. The author chose the local installation method and referenced two CSDN blogs for the detailed steps.
2. Code Development
2.1 Front‑end
The front‑end uses the Element UI Vue framework. The official OnlyOffice API documentation is consulted. The required JavaScript file must be added, and the document server address is replaced with the actual deployment address.
<div id="placeholder"></div>
<script type="text/javascript" src="https://documentserver/web-apps/apps/api/documents/api.js"></script>
const config = {
document: {
mode: 'edit',
fileType: 'docx',
key: String(Math.floor(Math.random() * 10000)),
title: route.query.name + '.docx',
url: import.meta.env.VITE_APP_API_URL + `/getFile/${route.query.id}`,
permissions: {
comment: true,
download: true,
modifyContentControl: true,
modifyFilter: true,
edit: true,
fillForms: true,
review: true
}
},
documentType: 'word',
editorConfig: {
user: { id: 'liu', name: 'liu' },
customization: { plugins: false, forcesave: true },
lang: 'zh',
callbackUrl: import.meta.env.VITE_APP_API_URL + '/callback',
height: '100%',
width: '100%'
}
};
new window.DocsAPI.DocEditor('onlyoffice', config); import.meta.env.VITE_APP_API_URLshould be replaced with the actual back‑end address, e.g., http://192.168.123.123:8089/getFile/12. The callbackUrl receives edit‑save callbacks.
2.2 Back‑end
The back‑end is a Spring Boot application. Maven dependencies for httpclient and httpmime are required. The core controller provides two endpoints: /getFile/{meeting_id} – reads the meeting‑minute file from the path stored in the database and streams it as an octet‑stream. /callback – handles OnlyOffice callbacks (status 1‑7) and triggers file saving when appropriate.
@RestController
public class OnlyOfficeController {
@Autowired
private IMeetingTableService meetingTableService;
private String meetingMinutesFilePath;
@GetMapping("/getFile/{meeting_id}")
public ResponseEntity<byte[]> getFile(HttpServletResponse response, @PathVariable Long meeting_id) throws IOException {
MeetingTable meetingTable = meetingTableService.selectMeetingTableById(meeting_id);
meetingMinutesFilePath = meetingTable.getMeetingMinutesFilePath();
if (meetingMinutesFilePath == null || "".equals(meetingMinutesFilePath)) {
return null;
}
File file = new File(meetingMinutesFilePath);
FileInputStream fis = new FileInputStream(file);
byte[] buffer = new byte[fis.available()];
fis.read(buffer);
fis.close();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
headers.setContentDispositionFormData("attachment", URLEncoder.encode(file.getName(), "UTF-8"));
return new ResponseEntity<>(buffer, headers, HttpStatus.OK);
}
@PostMapping("/callback")
public ResponseEntity<Object> handleCallback(@RequestBody CallbackData callbackData) {
Integer status = callbackData.getStatus();
switch (status) {
case 2:
String url = callbackData.getUrl();
try { saveFile(url); } catch (Exception e) { System.out.println("保存文件异常"); }
break;
// other cases omitted for brevity
}
return ResponseEntity.ok(Collections.singletonMap("error", 0));
}
public void saveFile(String downloadUrl) throws URISyntaxException, IOException {
HttpsKitWithProxyAuth.downloadFile(downloadUrl, meetingMinutesFilePath);
}
// CallbackData class omitted for brevity
}A utility class HttpsKitWithProxyAuth encapsulates an Apache HttpClient with optional HTTP or SOCKS proxy support, connection‑pool management, and helper methods for GET, POST (JSON, form‑urlencoded, multipart), and file download.
3. Problem Summary
3.1 Access Failure
After deployment, the service may not be reachable. Verify the service status with:
systemctl status ds*3.2 Word Loading Failure
Edit the configuration files under /etc/onlyoffice/documentserver. In local.json set all token entries to false. In default.json set request-filtering-agent to true, token.enable to false, and rejectUnauthorized to false. Restart the document server after changes.
3.3 Backend Token Verification Issue
If the back‑end requires a token, disable its verification for the OnlyOffice endpoints. Example Spring Security configuration:
@Bean
protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http
.csrf(csrf -> csrf.disable())
.headers(h -> h.cacheControl(cache -> cache.disable()).frameOptions(o -> o.sameOrigin()))
.exceptionHandling(e -> e.authenticationEntryPoint(unauthorizedHandler))
.sessionManagement(s -> s.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(r -> {
r.antMatchers("/callback", "/getFile/*", "/login", "/register", "/captchaImage").permitAll();
r.antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll();
r.antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll();
r.anyRequest().authenticated();
})
.logout(l -> l.logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler))
.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class)
.build();
}3.4 Document URL Access Issue
If you prefer a direct URL like http://192.168.123.123:8089/word/1234.docx, expose the document through a reverse proxy (e.g., Nginx) that maps /word/1234.docx to the actual file location. You can also test the deployment with an online sample document, e.g.,
https://d2nlctn12v279m.cloudfront.net/assets/docs/samples/zh/demo.docx, and replace the front‑end url with that link.
4. Afterword
The author notes that after two to three days of trial and error, the integration succeeded and the document editing, saving, and loading functions work as expected.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java Architect Handbook
Focused on Java interview questions and practical article sharing, covering algorithms, databases, Spring Boot, microservices, high concurrency, JVM, Docker containers, and ELK-related knowledge. Looking forward to progressing together with you.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
