博客

Mac 下使用 Homebrew 安装 Nginx 并发布 Cesium 地形与影像切片

在 Apple Silicon Mac 环境下,通过 Homebrew 安装 Nginx,并使用 Nginx 静态发布 Cesium 可访问的地形切片、影像切片等资源。

1. 文档说明#

适用场景:

  • 发布 Cesium quantized-mesh 地形切片;
  • 发布本地影像瓦片;
  • 供本地 Vue / Cesium 前端项目访问;
  • 解决 Cesium 访问本地切片时的跨域问题;
  • 使用简单静态文件服务替代复杂 GIS 服务进行本地调试。

本文示例使用的本地资源根目录为:

bash
/Volumes/Lenovo/xlgl/terrain/ # Cesium 地形切片目录,包含 layer.json 和 0/1/2... 等层级目录 /Volumes/Lenovo/xlgl/imagery/ # 影像切片目录,可选 如果当前阶段只发布 terrain 地形数据,则只需要保证以下目录存在: ```bash /Volumes/Lenovo/xlgl/terrain/

2. 安装 Nginx#

2.1 使用 Homebrew 安装#

在终端执行:

bash
brew install nginx

安装完成后,Homebrew 会输出类似信息:

bash
==> Caveats Docroot is: /opt/homebrew/var/www The default port has been set in /opt/homebrew/etc/nginx/nginx.conf to 8080 so that nginx can run without sudo. nginx will load all files in /opt/homebrew/etc/nginx/servers/. To start nginx now and restart at login: brew services start nginx Or, if you don't want/need a background service you can just run: /opt/homebrew/opt/nginx/bin/nginx -g daemon\ off\;

2.2 Homebrew Nginx 的关键路径#

Apple Silicon Mac 下,Homebrew 默认安装在:

bash
/opt/homebrew

Nginx 相关路径通常如下:

bash
/opt/homebrew/etc/nginx/nginx.conf # Nginx 主配置文件 /opt/homebrew/etc/nginx/servers/ # 自定义 server 配置目录 /opt/homebrew/var/www # 默认网站根目录 /opt/homebrew/opt/nginx/bin/nginx # Nginx 可执行文件

Homebrew 安装的 Nginx 默认监听端口一般为:

bash
8080

这样做的好处是无需使用 sudo 即可启动 Nginx。


3. 准备 Cesium 切片目录#

调整后的本地磁盘目录结构如下:

bash
/Volumes/Lenovo/xlgl/ ├── terrain/ │ ├── layer.json │ ├── 0/ │ ├── 1/ │ ├── 2/ │ └── ... │ └── imagery/ ├── 0/ ├── 1/ ├── 2/ └── ...

其中:

目录 说明
/Volumes/Lenovo/xlgl/terrain/ Cesium 地形切片目录
/Volumes/Lenovo/xlgl/terrain/layer.json Cesium 地形服务入口文件
/Volumes/Lenovo/xlgl/terrain/0/0/0.terrain quantized-mesh 地形切片示例
/Volumes/Lenovo/xlgl/imagery/ 影像切片目录,可选

检查地形目录是否存在:

bash
ls /Volumes/Lenovo/xlgl/terrain/

至少应能看到:

bash
layer.json 0 1 2 ...

如果你的当前目录仍然是:

bash
/Volumes/Lenovo/xlgl/terrain/xlgl/

可以先把里面的内容移动到上一层:

bash
mv /Volumes/Lenovo/xlgl/terrain/xlgl/* /Volumes/Lenovo/xlgl/terrain/

确认移动完成后,可根据实际情况删除空目录:

bash
rmdir /Volumes/Lenovo/xlgl/terrain/xlgl

影像目录如有同样情况,也可以调整:

bash
mv /Volumes/Lenovo/xlgl/imagery/xlgl/* /Volumes/Lenovo/xlgl/imagery/ rmdir /Volumes/Lenovo/xlgl/imagery/xlgl

4. 新建 Nginx 配置文件#

4.1 创建配置文件#

Homebrew Nginx 会自动加载以下目录中的配置文件:

bash
/opt/homebrew/etc/nginx/servers/

因此,新建一个 Cesium 切片服务配置文件:

bash
nano $(brew --prefix)/etc/nginx/servers/cesium_tiles.conf

也可以直接使用完整路径:

bash
nano /opt/homebrew/etc/nginx/servers/cesium_tiles.conf

5. Nginx 配置内容#

将下面内容写入:

bash
/opt/homebrew/etc/nginx/servers/cesium_tiles.conf

完整配置如下:

nginx
server { listen 8080; server_name localhost; # 只发布 /Volumes/Lenovo/xlgl 下面的内容 # Nginx root 会将请求 URI 拼接到该目录后面 root /Volumes/Lenovo/xlgl; # terrain 根路径 location /terrain/ { autoindex off; add_header Access-Control-Allow-Origin * always; add_header Access-Control-Allow-Methods "GET, OPTIONS" always; add_header Access-Control-Allow-Headers "*" always; } # quantized-mesh / .terrain 文件 location ~ ^/terrain/.*\.terrain$ { default_type application/octet-stream; # Cesium quantized-mesh 地形切片通常是 gzip 编码 add_header Content-Encoding gzip always; add_header Access-Control-Allow-Origin * always; add_header Access-Control-Allow-Methods "GET, OPTIONS" always; add_header Access-Control-Allow-Headers "*" always; } # layer.json location ~ ^/terrain/.*layer\.json$ { default_type application/json; add_header Access-Control-Allow-Origin * always; add_header Access-Control-Allow-Methods "GET, OPTIONS" always; add_header Access-Control-Allow-Headers "*" always; } # 影像切片,可选 location /imagery/ { autoindex off; add_header Access-Control-Allow-Origin * always; add_header Access-Control-Allow-Methods "GET, OPTIONS" always; add_header Access-Control-Allow-Headers "*" always; } # 可选:处理浏览器预检请求 if ($request_method = OPTIONS) { return 204; } }

6. root 路径映射说明#

本配置使用的是:

nginx
root /Volumes/Lenovo/xlgl;

在 Nginx 中,root 的作用是将请求 URI 直接拼接到 root 指定的目录后面。

也就是说:

text
磁盘根目录 + 请求 URI = 实际文件路径

6.1 layer.json 映射关系#

请求地址:

text
http://localhost:8080/terrain/layer.json

实际访问文件:

bash
/Volumes/Lenovo/xlgl/terrain/layer.json

6.2 terrain 文件映射关系#

请求地址:

text
http://localhost:8080/terrain/0/0/0.terrain

实际访问文件:

bash
/Volumes/Lenovo/xlgl/terrain/0/0/0.terrain

6.3 影像切片映射关系#

如果存在影像切片:

bash
/Volumes/Lenovo/xlgl/imagery/

则请求地址类似:

text
http://localhost:8080/imagery/0/0/0.png

实际访问文件:

bash
/Volumes/Lenovo/xlgl/imagery/0/0/0.png

7. root 与 alias 的区别说明#

当前配置使用 root,原因是 URL 路径和磁盘目录结构一致。

例如:

text
URL: /terrain/layer.json 磁盘: /Volumes/Lenovo/xlgl/terrain/layer.json

这种情况下,使用 root 最简单。

如果 URL 路径和磁盘路径不一致,例如希望:

text
http://localhost:8080/terrain/

映射到:

bash
/Volumes/Lenovo/xlgl/terrain_data/

此时才更适合使用 alias。

当前不需要使用 alias。


8. 检查 Nginx 配置是否正确#

保存配置后,执行:

bash
nginx -t

如果提示:

bash
nginx: the configuration file /opt/homebrew/etc/nginx/nginx.conf syntax is ok nginx: configuration file /opt/homebrew/etc/nginx/nginx.conf test is successful

说明配置语法正确。

如果命令找不到,可以使用完整路径:

bash
/opt/homebrew/opt/nginx/bin/nginx -t

9. 启动 Nginx#

9.1 使用 Homebrew 服务方式启动#

推荐方式:

bash
brew services start nginx

启动后,Nginx 会作为后台服务运行,并在系统登录后自动启动。

9.2 重启 Nginx#

修改配置后,需要重启 Nginx:

bash
brew services restart nginx

9.3 停止 Nginx#

bash
brew services stop nginx

9.4 前台运行方式#

如果不希望作为后台服务运行,也可以使用:

bash
/opt/homebrew/opt/nginx/bin/nginx -g 'daemon off;'

10. 测试访问#

10.1 测试 layer.json#

在浏览器中访问:

text
http://localhost:8080/terrain/layer.json

如果能看到 JSON 内容,说明地形服务入口文件可以访问。

也可以使用 curl 测试:

bash
curl -I http://localhost:8080/terrain/layer.json

正常情况下应返回类似:

text
HTTP/1.1 200 OK Content-Type: application/json Access-Control-Allow-Origin: *

10.2 测试 terrain 文件#

访问:

text
http://localhost:8080/terrain/0/0/0.terrain

或使用:

bash
curl -I http://localhost:8080/terrain/0/0/0.terrain

正常情况下应包含:

text
HTTP/1.1 200 OK Content-Type: application/octet-stream Content-Encoding: gzip Access-Control-Allow-Origin: *

10.3 测试影像切片#

如果配置了影像切片,可以访问:

text
http://localhost:8080/imagery/0/0/0.png

实际路径对应:

bash
/Volumes/Lenovo/xlgl/imagery/0/0/0.png

11. Cesium 前端调用示例#

11.1 加载 Cesium 地形#

在 Cesium 中可以这样加载:

javascript
const viewer = new Cesium.Viewer("cesiumContainer", { terrainProvider: await Cesium.CesiumTerrainProvider.fromUrl( "http://localhost:8080/terrain/" ) });

如果你的 Cesium 版本较旧,也可能使用:

javascript
const terrainProvider = new Cesium.CesiumTerrainProvider({ url: "http://localhost:8080/terrain/" }); const viewer = new Cesium.Viewer("cesiumContainer", { terrainProvider });

11.2 加载本地影像切片#

如果影像切片是 XYZ 结构,可以使用:

javascript
const imageryProvider = new Cesium.UrlTemplateImageryProvider({ url: "http://localhost:8080/imagery/{z}/{x}/{y}.png" }); viewer.imageryLayers.addImageryProvider(imageryProvider);

具体 {z}/{x}/{y} 是否正确,需要根据实际切片目录结构确定。


12. 常见问题处理#

12.1 访问 layer.json 返回 404#

检查文件是否真实存在:

bash
ls /Volumes/Lenovo/xlgl/terrain/layer.json

如果不存在,说明地形目录路径不正确。

同时确认 Nginx 配置中的 root 是否为:

nginx
root /Volumes/Lenovo/xlgl;

12.2 访问 terrain 文件返回 404#

检查示例切片是否存在:

bash
ls /Volumes/Lenovo/xlgl/terrain/0/0/0.terrain

如果不存在,查看真实的地形切片层级结构,例如:

bash
find /Volumes/Lenovo/xlgl/terrain -name "*.terrain" | head

根据实际结果调整访问地址。

12.3 Cesium 报跨域错误#

确保配置中包含:

nginx
add_header Access-Control-Allow-Origin * always; add_header Access-Control-Allow-Methods "GET, OPTIONS" always; add_header Access-Control-Allow-Headers "*" always;

修改配置后执行:

bash
nginx -t brew services restart nginx

12.4 Cesium 地形无法正常解析#

重点检查 .terrain 文件是否返回了:

text
Content-Encoding: gzip

对应 Nginx 配置为:

nginx
location ~ ^/terrain/.*\.terrain$ { default_type application/octet-stream; add_header Content-Encoding gzip always; }

如果你的 .terrain 文件本身不是 gzip 编码,则不能强制添加:

nginx
add_header Content-Encoding gzip always;

但 Cesium quantized-mesh 地形切片多数情况下是 gzip 编码的,需要该响应头。

12.5 8080 端口被占用#

检查端口占用:

bash
lsof -i :8080

如果已有其他服务占用,可以修改配置中的端口,例如改为:

nginx
listen 8090;

然后重启:

bash
nginx -t brew services restart nginx

访问地址也相应改为:

text
http://localhost:8090/terrain/layer.json

12.6 配置修改后不生效#

执行:

bash
nginx -t brew services restart nginx

如果仍不生效,可以查看当前 Nginx 是否由 Homebrew 启动:

bash
brew services list

13. 推荐最终目录结构#

建议最终目录结构保持清晰,便于后续扩展:

bash
/Volumes/Lenovo/xlgl/ ├── terrain/ │ ├── layer.json │ ├── 0/ │ ├── 1/ │ ├── 2/ │ └── ... │ ├── imagery/ │ ├── 0/ │ ├── 1/ │ ├── 2/ │ └── ... │ ├── vector/ │ └── ... │ └── docs/ └── ...

Nginx 配置文件:

bash
/opt/homebrew/etc/nginx/servers/cesium_tiles.conf

14. 最终访问地址汇总#

类型 URL
地形 layer.json http://localhost:8080/terrain/layer.json
地形服务根地址 http://localhost:8080/terrain/
terrain 示例切片 http://localhost:8080/terrain/0/0/0.terrain
影像切片根地址 http://localhost:8080/imagery/
影像切片示例 http://localhost:8080/imagery/0/0/0.png

15. 完整操作命令汇总#

bash
# 1. 安装 Nginx brew install nginx # 2. 创建 Nginx server 配置目录,通常已存在 mkdir -p $(brew --prefix)/etc/nginx/servers # 3. 新建 Cesium 切片配置文件 nano $(brew --prefix)/etc/nginx/servers/cesium_tiles.conf # 4. 检查配置 nginx -t # 5. 启动 Nginx brew services start nginx # 6. 修改配置后重启 brew services restart nginx # 7. 测试 layer.json curl -I http://localhost:8080/terrain/layer.json # 8. 测试 terrain 文件 curl -I http://localhost:8080/terrain/0/0/0.terrain

16. 当前配置结论#

当前配置适合本地 Cesium 地形和影像切片调试。

核心点如下:

  1. 使用 Homebrew 安装 Nginx;
  2. 使用 /opt/homebrew/etc/nginx/servers/cesium_tiles.conf 管理自定义配置;
  3. 使用 root /Volumes/Lenovo/xlgl; 保持 URL 与磁盘目录结构一致;
  4. 地形访问地址为:
text
http://localhost:8080/terrain/
  1. layer.json 实际映射到:
bash
/Volumes/Lenovo/xlgl/terrain/layer.json
  1. .terrain 文件需要正确设置:
nginx
Content-Encoding: gzip
  1. 所有 Cesium 资源路径均添加 CORS 响应头,方便前端项目直接访问;