You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现后端作为前端与外部服务器的文件获取桥梁?

解决方案

1. 修正控制器路由与参数接收

首先将控制器路由改为动态参数匹配,适配前端请求的URL结构,同时正确处理不同类型的文件返回:

import { Controller, Get, Param, StreamableFile, Response } from '@nestjs/common';
import { GeomService } from './geom.service';

@Controller()
export class GeomController {
  constructor(private readonly geomService: GeomService) {}

  // 匹配动态路径:/geometrictiles/{layername}/{z}/{x}/{y}.{ext}
  @Get('/geometrictiles/:layername/:z/:x/:y.:ext')
  async getGeoTiles(
    @Param('layername') layername: string,
    @Param('z') z: string,
    @Param('x') x: string,
    @Param('y') y: string,
    @Param('ext') ext: string,
    @Response() res,
  ) {
    const fileData = await this.geomService.getGeometricFile(layername, z, x, y, ext);
    // 根据扩展名设置响应Content-Type
    res.setHeader('Content-Type', this.getContentType(ext));
    
    if (['pbf', 'jpg', 'pdf'].includes(ext.toLowerCase())) {
      return new StreamableFile(fileData);
    } else {
      res.send(fileData);
    }
  }

  // 辅助方法:映射扩展名到对应Content-Type
  private getContentType(ext: string): string {
    const typeMap = {
      pbf: 'application/x-protobuf',
      jpg: 'image/jpeg',
      pdf: 'application/pdf',
      csv: 'text/csv',
      json: 'application/json',
    };
    return typeMap[ext.toLowerCase()] || 'application/octet-stream';
  }
}

2. 重构服务层方法,适配多文件类型

服务层需根据文件类型设置响应类型,确保获取原始数据不被篡改:

import { Injectable, ForbiddenException } from '@nestjs/common';
import { HttpService } from '@nestjs/axios';
import { catchError, map } from 'rxjs/operators';

@Injectable()
export class GeomService {
  private readonly privateServerBase = 'http://XXX.XXX.XXX.XXX/geometrictiles';

  constructor(private readonly httpService: HttpService) {}

  async getGeometricFile(
    layername: string,
    z: string,
    x: string,
    y: string,
    ext: string,
  ) {
    const targetUrl = `${this.privateServerBase}/${layername}/${z}/${x}/${y}.${ext}`;
    // 二进制文件用stream模式,文本类用json模式
    const responseType = ['pbf', 'jpg', 'pdf'].includes(ext.toLowerCase()) 
      ? 'stream' 
      : 'json';

    return this.httpService.get(targetUrl, { responseType })
      .pipe(
        map(res => responseType === 'stream' ? res.data : res.data),
        catchError(() => {
          throw new ForbiddenException('私有地图服务器请求失败');
        }),
      )
      .toPromise();
  }
}

3. 关键修复点说明

  • 动态路由:通过:layername、:z等占位符,完美匹配前端请求的URL结构,无需硬编码参数。
  • 响应类型适配:二进制文件(PBF、JPG、PDF)使用stream响应类型,避免JSON解析导致文件损坏;文本类(JSON、CSV)直接获取原始数据。
  • Content-Type设置:正确设置响应头,让前端能识别文件类型并正确处理。
  • 错误统一处理:捕获私有服务器请求异常,返回明确的错误信息。

4. 测试验证

  • JSON测试:请求http://localhost:3001/geometrictiles/mylayer/11/585/783.json,应返回私有服务器对应JSON数据。
  • PBF测试:请求http://localhost:3001/geometrictiles/mylayer/11/585/783.pbf,应返回原始二进制文件,可通过地图工具验证完整性。
  • 图片测试:请求http://localhost:3001/geometrictiles/mylayer/11/585/783.jpg,浏览器应直接显示图片。

内容的提问来源于stack exchange,提问作者Jorge Monroy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 14:27:12