1

我有一个 loopback4 控制器来获取并在服务器上创建一些文件。所有文件都存储在具有更深目录的目录结构中。它可能看起来像这样:

├── WA2114
│   ├── 300dpi
│   │   ├── WA2114_Frontal.jpg
│   │   └── WA2114_entnehmen.jpg
│   ├── web
│   │   ├── WA2114-anwendung-Aufbewahrung.jpg
│   │   └── WA2114_Verpackung_NEU.jpg
│   ├── Produktdatenblatt
│   │   └── 2114-000.pdf

我想要一个方法,根据调用的 RestAPI-Route 获取所有文件:

GET /files/{category}

如果我打电话GET /files/WA2114,我想得到一个位于 WA2114/ 下的所有文件的列表。如果我打电话GET /files/WA2114/300dpi,我只想要更深的文件夹中的文件../300dpi。我希望很清楚,目标是什么。通过 . 上传新文件需要相同的逻辑POST /files/{category}

我已经尝试过这里描述的解决方案:https ://lideo.github.io/loopback.io/doc/en/lb4/Routes.html但没有成功。

我已经为顶层目录设置了路由。但是更深的目录无法动态访问,因为路由装饰器似乎被粘在了级别上,并且变量中不允许使用斜线。我不想创建几十种方法来处理每个目录级别。

我当前的控制器(简化):

export class FileController
{
    constructor(@repository(FileRepository) public fileRepository: FileRepository)
    {
    }

    @get('/files/{category}', {
        responses: {
            '200': {
                description: 'Array of File model instances of the specified category',
                content:     {
                    'application/json': {
                        schema: {type: 'array', items: {'x-ts-type': File}}
                    }
                }
            }
        }
    })
    async findbyCategory(@param.path.string('category') category: string): Promise<File[]>
    {
        return await this.fileRepository.findByCategory(category);
    }
}

我如何装饰控制器方法才能使用相同的方法动态获取 /files/a 和 files/a/b/c?

我已经在 php/Symphony 中做了类似的事情,看起来像这样: @Route("/files/{category}", methods={"GET"}, requirements={"category"=".+"}). 这.+就是这里的魔力。现在我必须用 loopback4 重建代码,并且必须重构路由,但我在这个上失败了。有人对此有解决方案吗?

4

1 回答 1

1

我已经为顶层目录设置了路由。但是更深的目录无法动态访问,因为路由装饰器似乎被粘在了级别上,并且变量中不允许使用斜线。我不想创建几十种方法来处理每个目录级别。

  • App会处理你的请求,sequence.ts根据你的请求地址和参数等找到对应的路由器。

export class MySequence implements SequenceHandler {
    constructor(
        @inject(SequenceActions.FIND_ROUTE) protected findRoute: FindRoute,
        @inject(SequenceActions.PARSE_PARAMS) protected parseParams: ParseParams,
        @inject(SequenceActions.INVOKE_METHOD) protected invoke: InvokeMethod,
        @inject(SequenceActions.SEND) public send: Send,
        @inject(SequenceActions.REJECT) public reject: Reject,
    ) { }

    async handle(context: RequestContext) {
        try {
            const { request, response } = context;
            const route = this.findRoute(request); // <= here!!! find router by request
            const args = await this.parseParams(request, route);
            const result = await this.invoke(route, args);
            this.send(response, result);
        } catch (err) {
            this.reject(context, err);
        }
    }
}

  • 您需要“欺骗”FindRoute并将以下请求分配给同一路由器

认为:

我们有一个控制器A,其中一个 api 是@get("/api/{category}")

前:

/api/dir-1=> url= /apiparam= dir-1=> 控制器A

/api/dir-1/file-2=> url= /api/dir-1param= file-2=> (找不到控制器)

/api/dir-1/dir-2/file-3=> url= /api/dir-1/dir-2param= file-3=> (找不到控制器)

    async handle(context: RequestContext) {
        try {
            const { request, response } = context;

            // !
            if (
                request.method === "GET" && request.url === "/api/"
            ) {
                request.url = `/files/'${request.url.slice(7).replace(/\//gi, '----')}'`;
            }

            const route = this.findRoute(request);
            const args = await this.parseParams(request, route);
            const result = await this.invoke(route, args);
            this.send(response, result);
        } catch (err) {
            this.reject(context, err);
        }
    }

后:

/api/dir-1=> url=/api参数= dir-1=> 控制器A

/api/dir-1/file-2=> url=/api参数= dir-1----file-2=> 控制器A

/api/dir-1/dir-2/file-3=> url=/api参数= dir-1----dir-2----file-3=> 控制器A

  • 完成,现在您可以在控制器中处理文件了A。但我认为这不是一个好的解决方案,你需要新建一个FindRoute并将相应的逻辑放入其中。

有关详细信息,请参阅我的示例项目

于 2019-08-17T15:18:56.803 回答