1、运行collabora
version: '3'
services:
collabora:
image: collabora/code:25.04.3.1.1
cap_add:
- MKNOD
ports:
- "9980:9980"
environment:
- extra_params= >
--o:ssl.enable=false
--o:server_name=192.168.88.18:9000
--o:storage.wopi.host[0]=192.168.88.18:8001
--o:storage.wopi.host[1]=192.168.88.18:9000
--o:user_interface.use_integration_theme=false
- domain=192\\.168\\.88\\.18\\:9000
extra_hosts:
- "host.docker.internal:host-gateway"
注意,这个domain是允许wopi服务访问collobora的相关api。这里的192.168.88.18是部署collabora的docker服务器地址。
验证collaboca部署是否成功,通过(http://192.168.88.18/hosting/discovery)并且获取collabora的urlsrc地址,这个地址(http://192.168.88.18/browser/e724e42045/cool.html?)我们需要在后续生成iframe的地址时使用。

2、编写wopi服务
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.Map;
@RestController
@RequestMapping("/wopi/files")
public class WopiController {
@GetMapping("/{fileId}")
public ResponseEntity<?> checkFileInfo(@PathVariable String fileId) {
// 校验 token 是否有效
// 返回 JSON 包含文件信息
return ResponseEntity.ok(Map.of(
"BaseFileName", "tcn100安全.docx",
"Size", 12345,
"OwnerId", "user1",
"UserId", "user1",
"UserFriendlyName", "User One",
"UserCanWrite", true,
"SupportsLocks", true,
"SupportsUpdate", true
));
}
@GetMapping("/{fileId}/contents")
public ResponseEntity<Resource> getFile(@PathVariable String fileId, @RequestParam("access_token") String token) throws IOException {
// 从存储中获取文件
File file = new File("E:\\temp2\\tcn100安全.docx");
return ResponseEntity.ok()
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.body(new FileSystemResource(file));
}
@PostMapping("/{fileId}/contents")
public ResponseEntity<?> putFile(@PathVariable String fileId, @RequestParam("access_token") String token, InputStream fileStream) throws IOException {
// 将新内容保存到文件中
Files.copy(fileStream, Paths.get("/data/" + fileId), StandardCopyOption.REPLACE_EXISTING);
return ResponseEntity.ok().build();
}
@PostMapping("/{fileId}")
public ResponseEntity<?> handlePostOps(@PathVariable String fileId, @RequestHeader("X-WOPI-Override") String operation) {
// 处理 Lock/Unlock/RefreshLock 等
return ResponseEntity.ok().build();
}

3、配置nginx
注意:collabora与wopi服务必须使用nginx代理到同一个ip或域名下,否则会出现跨域错误。
server {
listen 9000;
server_name 192.168.88.18; # 或使用 IP,如 192.168.88.100
location / {
root /opt/www;
index index.html index.htm;
}
# Collabora 其它 API 转发 /hosting/discovery
location ^~ /hosting/ {
proxy_pass http://192.168.88.18:9980/hosting/;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location ^~ /browser/ {
proxy_pass http://192.168.88.18:9980/browser/;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
}
# WOPI 服务(Spring Boot)
location /wopi/ {
proxy_pass http://192.168.88.60:8001/wopi/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# main websocket path
location /cool/ {
proxy_pass http://192.168.88.18:9980;
proxy_set_header Host $host;
# WebSocket 关键头部
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# 其他常规头部
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_buffering off;
proxy_request_buffering off;
proxy_read_timeout 36000s;
}
4、编写一个前端页面,用于测试
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
</head>
<body>
<form action="http://192.168.88.18:9000/browser/e724e42045/cool.html?WOPISrc=http%3A%2F%2F192.168.88.18:9000%2Fwopi%2Ffiles%2F184c286689ad71c17864480299806084"
target="my-iframe" enctype="multipart/form-data" method="post">
<input name="access_token" value="test" type="hidden" />
<input type="submit" value="Load Collabora Online" />
</form>
</body>
</html>
注:http%3A%2F%2F192.168.88.18%2Fwopi%2Ffiles%2Ftest是【http://192.168.88.18/wopi/files/test】地址进行URL编码后的字符串,collabora的api要求是必须使用URL编译wopi服务路径。

使用nginx代理(非80端口的配置)
server {
listen 9000;
server_name 192.168.88.18; # 或使用 IP,如 192.168.88.100
location / {
root /opt/www;
index index.html index.htm;
}
# Collabora 其它 API 转发 /hosting/discovery
location ^~ /hosting/ {
proxy_pass http://192.168.88.18:9980/hosting/;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location ^~ /browser/ {
proxy_pass http://192.168.88.18:9980/browser/;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
}
# WOPI 服务(Spring Boot)
location /wopi/ {
proxy_pass http://192.168.88.60:8001/wopi/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# main websocket path
location /cool/ {
proxy_pass http://192.168.88.18:9980;
proxy_set_header Host $host;
# WebSocket 关键头部
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# 其他常规头部
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_buffering off;
proxy_request_buffering off;
proxy_read_timeout 36000s;
}
}
文中配置的一些内容
如果你使用frp网络穿透,则需要将docker运行脚本作如下变更即可
version: '3'
services:
collabora:
image: collabora/code:25.04.3.1.1
cap_add:
- MKNOD
ports:
- "9980:9980"
volumes:
- /dev/null:/usr/share/loolwsd/loleaflet/dist/admin/admin.html
environment:
- extra_params= >
--o:ssl.enable=false
--o:server_name=dybai.net:6001
--o:storage.wopi.host[0]=172.18.17.16:8001
--o:storage.wopi.host[1]=dybai.net:6001
--o:user_interface.use_integration_theme=false
- domain=172\\.18\\.17\\.16\\:18080
- aliasgroup1=http:\\//dybai\\.net
extra_hosts:
- "host.docker.internal:host-gateway"