Как обслуживать статические изображения в NestJS

#javascript #node.js #express #mean-stack #nestjs

#javascript #node.js #выразить #имеется в виду-стек #nestjs

Вопрос:

Я начал изучать MEAN stack, и когда я перешел на Express, я увидел, что в express Framework существует дополнительный уровень, который называется NestJS. В нем было все, что я хотел, и у него был синтаксис, подобный Angular, поэтому он был идеальным для меня.

Но каждый новый шаг — это кошмар, документация вообще бесполезна. Сейчас я борюсь с фреймворком, чтобы добиться возможности обслуживать изображения и не использовать API для такого рода вызовов.

Я перепробовал все, что нашел в Интернете, например:

main.ts

 import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import * as bodyParser from 'body-parser';
import * as express from 'express';
import { join } from 'path';

import { NestExpressApplication } from '@nestjs/platform-express';



declare const module: any;

async function bootstrap() {
  const app = await NestFactory.create<NestExpressApplication>(AppModule);

  app.useStaticAssets(join(__dirname, '..', 'public'));




  app.enableCors({
    origin: true,
    methods: 'GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS',
    credentials: true,
  });

//I tried this 2 options (https://docs.nestjs.com/techniques/mvc) (https://whatthecode.dev/serve-static-files-with-nest-js/)
  app.use('/resources', express.static(process.cwd()   '\resources'));
  app.useStaticAssets(join(__dirname, '..', '\public'));

  app.use(bodyParser.json({ limit: '50mb' }));
  app.use(bodyParser.urlencoded({ limit: '50mb', extended: true }));
 
  //console.log(process.cwd());


  await app.listen(3000);

  if (module.hot) {
    module.hot.accept();
    module.hot.dispose(() => app.close());
  }

}
bootstrap();

  

Я попытался поместить это в app.module следующим образом (это сработало, но всегда ищет index.html не изображения):

 
import { AnimalsModule } from './animals/animals.module';
import { SpeciesModule } from './species/species.module';
import { AuthModule } from './auth/auth.module';
import { UsersModule } from './users/users.module';
import { BreedModule } from './breed/breed.module';
import { StateModule } from './state/state.module';
import { PhotoModule } from './photo/photo.module';


@Module({
  imports: [
    ServeStaticModule.forRoot({
      rootPath: join(__dirname, '..', 'public'),   // <-- path to the static files
    }),
    TypeOrmModule.forRoot({
      type: 'mysql',
      host: 'localhost',
      port: 3306,
      username: 'root',
      password: '',
      database: 'nest',
      entities: [__dirname   '/**/*.entity{.ts,.js}'],
      synchronize: true,
    }),
    AnimalsModule,
    SpeciesModule,
    BreedModule,
    StateModule,
    AuthModule,
    UsersModule,
    PhotoModule,
  ],
})

//It seems that ignores this register and just uses the method signature options
@Module({
  imports: [MulterModule.register({
    dest: './resources/tmp',
    limits: { fieldSize: 25 * 1024 * 1024 * 1024, fileSize: 25 * 1024 * 1024 * 1024 }
  })],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule { }
  

Как, черт возьми, я могу обслуживать изображения или файлы и избегать маршрутизации api?

Спасибо всем.

Комментарии:

1. Учитывая такую конфигурацию (которая кажется приемлемой), не могли бы вы поделиться своей структурой каталогов статической папки public и простым GET, который вы пробовали для некоторого статического ресурса?

2. Привет, у меня есть такая структура: project / resources / tmp /files project / public (просто попробуйте это имя, потому что его чаще можно увидеть в примерах) И мой запрос GET помещается в браузер localhost:3000/resources/a.jpg или общедоступную папку. Если вам нужны другие вещи, скажите это мне. Большое спасибо

3. Тем не менее, вы настраиваете свой корневой путь следующим образом: rootPath: join(__dirname, '..', 'public') ?

4. Попробуйте поместить ваше a.jpg в project / public и ПОЛУЧИТЬ его через localhost:3000/a.jpg

5. Корневой путь: join(__dirname, ‘..’, ‘public’)? Находится во втором файле исходного вопроса, и я попробовал этот запрос, и он возвращает маршрут 404, не найденный firefox

Ответ №1:

Это то, что я сделал:

  1. в app.module.ts

      import { ServeStaticModule } from '@nestjs/serve-static/dist/serve-static.module';
     import { join } from 'path';
    
     @Module({
         imports: [
             ServeStaticModule.forRoot({
                 rootPath: join(__dirname, '..', 'public'),
             }),
         ],
     })
      
  2. Затем я создал «общедоступный» каталог на том же уровне, что и «src», «dir» и т.д.

  3. Файл доступен по адресу: https://my-url/file.jpg

Комментарии:

1. я сделал это, но у меня есть эта ошибка «ENOENT: нет такого файла или каталога», это показывает, что файл не найден в distpublicindex.html

2. Разрешение ошибки «такого файла нет» можно найти здесь: github.com/nestjs/nest-cli/issues/320 Дополнение CompilerOptions.assets сработало для меня.

Ответ №2:

Используйте useStaticAssets() метод ( ServeStaticModule предназначен для обслуживания статического контента, такого как SPA). Итак, в качестве минимального примера ваш main.ts должен выглядеть следующим образом):

 async function bootstrap() {
  const app = await NestFactory.create<NestExpressApplication>(AppModule);
  app.useStaticAssets(join(__dirname, '..', 'public'));
  await app.listen(3000);
}
  

В приведенном выше примере ваши ресурсы обслуживаются из корня вашего приложения (например http://localhost:3000/example.png .

Вы также можете передать параметры методу в oder, чтобы настроить путь, по которому обслуживаются ресурсы:

   app.useStaticAssets(join(__dirname, '..', 'public'), {
    prefix: '/public/',
  });
  

В этом примере ваш путь имеет префикс public (например http://localhost:3000/public/example.png )

Ответ №3:

Есть два способа обслуживать статический контент в NestJs . Либо используйте 1 , ЛИБО 2 .

1. Использование ServeStaticModule в app.module.ts

 import { Module } from '@nestjs/common';
import { ServeStaticModule } from '@nestjs/serve-static';
import { join } from 'path';
import { mainModule } from 'process'    
@Module({
  imports: [
    ServeStaticModule.forRoot({
      rootPath: join(__dirname, '..', 'public'),
    }),
  ],
})
export class AppModule {}
  

2. Использование NestExpressApplication в main.ts [Даже по умолчанию Nest Js использует только Express]

 import { NestFactory } from '@nestjs/core';
import { NestExpressApplication } from '@nestjs/platform-express';
import { join } from 'path';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create<NestExpressApplication>(
    AppModule,
  );

  app.useStaticAssets(join(__dirname, '..', 'public'));

  await app.listen(3000);
}
bootstrap();
  

Ответ №4:

добавьте это в main.ts замените «uploads» именем вашего каталога app.use(‘/uploads’,express.static(join(process.cwd(), ‘uploads’)));

Комментарии:

1. Не могли бы вы, пожалуйста, отредактировать это и объяснить, почему? В таком случае это также помогло бы другим людям обнаружить эту проблему, поскольку, скорее всего, автор первоначального вопроса уже решил проблему через 10 месяцев 😉

2. У меня это работает только для получения статического содержимого. Я могу загружать элементы без этого, но я этого не вижу

Ответ №5:

У меня была такая же проблема. Я также очень долго боролся с этой проблемой. Например: у вас есть папка для загрузки изображений. В App.module вам нужно использовать его:

     ServeStaticModule.forRoot({
  rootPath: join(__dirname, '..', 'client'),
}),
  

localhost: 3000/picture.png

если я использую папку «без клиента», мое изображение будет

 ServeStaticModule.forRoot({
  rootPath: join(__dirname, '..'),
}),
  

localhost: 3000 /клиент /picture.png

Ответ №6:

Идея @pzabrocki приводит меня к следующему минимально рабочему репозиторию: https://gitlab.com/hadrien-toma/nest-static-files

Чтобы поиграть с этим:

 git clone https://gitlab.com/hadrien-toma/nest-static-files
yarn install
yarn run start
  

Затем my-file.json подается в http://localhost:3333/my-file.json .

Ответ №7:

Отдельное модульное решение, затем импортируйте его в AppModule.

 import { Module } from '@nestjs/common';
import { ServeStaticModule } from '@nestjs/serve-static';
import { resolve } from 'path';

@Module({
    imports: [
        ServeStaticModule.forRoot(
            (() => {
                const publicDir = resolve('./public/files/');
                const servePath = '/files';

                return {
                    rootPath: publicDir,
                    // serveRoot - if you want to see files on another controller,
                    // e.g.: http://localhost:8088/files/1.png
                    serveRoot: servePath,
                    exclude: ['/api*'],
                };
            })()
        ),
    ],
})
export class PublicModule {}
  

Ответ №8:

Основной метод document nest с использованием модуля заключается в следующем:

 
 ServeStaticModule.forRoot({
    rootPath: join(__dirname, '..', 'upload'),   //  path to the static files image
 }),
  

Но если вы получаете ошибку при поиске index.html , вы можете использовать этот метод, который я также использовал

main.ts

 import * as express from 'express';

app.use(express.static(join(__dirname, '../upload')))
  

Ответ №9:

вы можете перейти в корневой каталог, если ваша папка загрузки находится в rootdir, затем укажите путь к папке в renderPath следующим образом.

 ServeStaticModule.forRoot({
  rootPath: join(__dirname, '../../'),
  renderPath: '/uploads',
})
  

Ответ №10:

Вы также можете использовать статический модуль express в nest js.

 // ...imports
import * as express from 'express';
import { join } from 'path';

async function bootstrap() {
    const app = await NestFactory.create(AppModule);
  
    // serve static assets from the client/dist folder, change this to the correct path for your project
    app.use(express.static(join(process.cwd(), '../client/dist/')));
  
    //... you config

   await app.listen(process.env.PORT);
 }
bootstrap();
  

Заслуга:https://whatthecode.dev/serve-static-files-with-nest-js