【问题标题】:GET http://localhost:4200/tour-x-b-cover.jpeg 404 (Not Found) - Broken Image Path(Not Shown)GET http://localhost:4200/tour-x-b-cover.jpeg 404(未找到)-损坏的图像路径(未显示)
【发布时间】:2022-01-28 01:42:23
【问题描述】:

我的旅行表列表显示除了图像封面之外的所有必需信息。我无法弄清楚为什么图像路径被破坏了。我怀疑我的后端代码为我的静态文件提供服务,但据我所知,一切似乎都很好。

在后端代码中,我有以下代码行用于在我的 app.js 文件中提供静态文件。

app.use(
  '/public/img/countries',
  express.static(`${__dirname}/public/img/countries`)
);
app.use('/public/img/tours', express.static(`${__dirname}/public/img/tours`));
app.use('/public/img/users', express.static(`${__dirname}/public/img/users`));

在我的游览处理程序函数 tourController.js 后端代码中,我有以下代码,因为它专门与图像有关。

const multerStorage = multer.memoryStorage();


const multerFilter = (req, file, cb) => {
  if (file.mimetype.startsWith('image')) {
    cb(null, true);
  } else {
    cb(new AppError('Not an image! Please upload only images.', 400), false);
  }
};

const upload = multer({
  storage: multerStorage,
  fileFilter: multerFilter
  // limits: { fileSize: maxSize }
});

exports.uploadTourImages = upload.fields([
  //req.files for fields
  { name: 'imageCover', maxCount: 1 },
  { name: 'images', maxCount: 3 }
]);


exports.resizeTourImages = catchAsync(async (req, res, next) => {
  if (!req.files.imageCover || !req.files.images) return next();

  // 1) Cover image
  req.body.imageCover = `tour-${req.params.id}-${Date.now()}-cover.jpeg`;

  await sharp(req.files.imageCover[0].buffer)
    .rotate()
    .resize(1903, 1268)
    .toFormat('jpeg')
    .jpeg({ quality: 90 })
    .toFile(`public/img/tours/${req.body.imageCover}`);

  req.body.images = [];

  await Promise.all(
    req.files.images.map(async (file, i) => {
    
      const filename = `tour-${req.params.id}-${Date.now()}-${i + 1}.jpeg`;

      await sharp(file.buffer)
        .rotate()
        .resize(1903, 1268)
        .toFormat('jpeg')
        .jpeg({ quality: 90 }) 
        .toFile(`public/img/tours/${filename}`);

      req.body.images.push(filename);
    })
  );

  next();
});

在我的后端模型上的工厂函数

exports.getAll = Model =>
  catchAsync(async (req, res, next) => {
    let filter = {};
    if (req.params.tourId) filter = { tour: req.params.tourId };

    //EXECUTE QUERY
    const features = new APIFeatures(Model.find(filter), req.query)
      .filter()
      .sort()
      .limitFields()
      .paginate();

    const doc = await features.query;

    //SEND REPONSE
    res.status(200).json({
      status: 'success',
      results: doc.length,
      data: {
        data: doc
      }
    });

    next();
  });

在我的前端,我的 tour-list.component.html 上有下面的表格代码

<p-table [value]="tours" styleClass="p-datatable-gridlines" responsiveLayout="scroll">
          <ng-template pTemplate="header">
            <tr>
              <th pSortableColumn="name">Name<p-sortIcon field="name"></p-sortIcon></th>
              <th>Image Cover</th>
              <th pSortableColumn="price">Price<p-sortIcon field="price"></p-sortIcon></th>
              <th pSortableColumn="ratingsAverage">
                Ratings Average <p-sortIcon field="ratingsAverage"></p-sortIcon>
              </th>
              <th pSortableColumn="country">Country<p-sortIcon field="country"></p-sortIcon></th>
              <th pSortableColumn="difficulty">
                Difficulty<p-sortIcon field="difficulty"></p-sortIcon>
              </th>
              <th pSortableColumn="availabilityDates">
                Availability Dates<p-sortIcon field="availabilityDates"></p-sortIcon>
              </th>
              <th pSortableColumn="maxGroupPair">
                Maximum Group Pairs<p-sortIcon field="maxGroupPair"></p-sortIcon>
              </th>
              <th pSortableColumn="minimumAge">
                Minimum Age<p-sortIcon field="minimumAge"></p-sortIcon>
              </th>
              <th pSortableColumn="dateCreated">
                Date Created<p-sortIcon field="dateCreated"></p-sortIcon>
              </th>
              <th></th>
            </tr>
          </ng-template>
          <ng-template pTemplate="body" let-tour>
            <tr>
              <td>{{ tour.name }}</td>
              <td><img [src]="tour.imageCover" width="100px" height="67px" alt="" /></td>
              <td>{{ tour.price }}</td>
              <td>{{ tour.ratingsAverage }}</td>
              <td>{{ tour.country.name }}</td>
              <td>{{ tour.difficulty }}</td>
              <td>{{ tour.availabilityDates }}</td>
              <td>{{ tour.maxGroupPair }}</td>
              <td>{{ tour.minimumAge }}</td>
              <td>{{ tour.dateCreated | date: 'longDate' }}</td>
            </tr>
          </ng-template>
        </p-table>

我的 tours-list.component.ts 文件有以下代码

import { Component, OnInit } from '@angular/core';
import { ToursService } from '@tourafrika/tours';

@Component({
  selector: 'admin-tours-list',
  templateUrl: './tours-list.component.html',
  styles: []
})
export class ToursListComponent implements OnInit {
  tours = [];

  constructor(private tourService: ToursService) {}

  ngOnInit(): void {
    this._getTours();
  }

  private _getTours() {
    this.tourService.getTours().subscribe((tours) => {
      this.tours = tours;
    });
  }
}

我前端的库模型代码具有以下代码。

import { Country } from './country';
import { User } from './user';

export class Tour {
  id?: string;
  name?: string;
  slug?: string;
  country?: Country;
  duration?: number;
  maxGroupPair?: number;
  singleSupplement?: number;
  difficulty?: string;
  ratingsAverage?: number;
  ratingsQuantity?: number;
  price?: number;
  priceDiscount?: number;
  overview?: string;
  imageCover?: string;
  images?: string[];
  dateCreated?: string;
  availabilityDates?: string[];
  isFeatured?: boolean;
  secretTour?: string;
  minimumAge?: string;
  departureLocation?: string;
  locations?: string;
  guides?: [User];
}

export interface ITourListResponse {
  status: string;
  results: number;
  data: { data: Tour[] };
}

我的 tours.service.ts 服务文件有以下代码。

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { Tour, ITourListResponse } from '../models/tour';
import { map } from 'rxjs/operators';
import { environment } from '@env/environment';

@Injectable({
  providedIn: 'root'
})
export class ToursService {
  apiURLTours = environment.apiUrl + 'tours';
  constructor(private http: HttpClient) {}

  getTours(): Observable<Tour[]> {
    return this.http
      .get<ITourListResponse>(this.apiURLTours)
      .pipe(map((response: ITourListResponse) => response.data.data));
  }

谢谢!

【问题讨论】:

  • 请分享您的 API 响应数据。
  • API 响应非常大,但与 Image Cove 相关的是:{ "status": "success", "results": 12, "data": { "data": [ " imageCover": "tour-61df1a042001bcc1821b17d6-1643097859361-cover.jpeg", ] }
  • 我正在通过私有 _getTours() 方法在我的 tours-list.component.ts 文件上运行 console.log(this.tours) 获取所有数据并提取 console.log(this.tours ) 带有显示 imageCover 的图像封面的数组:“tour-61df19e82001bcc1821b17cc-1643098212886-cover.jpeg”
  • 您是否将这些图像包含在您的前端资产文件夹中?
  • 不,我没有。我只是通过 Postman 的更新使用我的后端代码上传了这些图像。 .现在我只想获取数据库中的一些数据字段,并通过运行私有 _getTours 用这些数据填充前端。除了封面图片路径损坏之外,所有数据都通过前端。

标签: node.js angular typescript express


【解决方案1】:

我已经通过运行以下代码重新定义我的 imageCover 路径来完全重组后端的 toursController.ts 文件中的代码来解决这个问题。现在一切都好!

 const { file } = req;
  let imagepath;

  if (file) {
    const fileName = req.file.filename;
    const basePath = `${req.protocol}://${req.get('host')}/public/img/tours/`;
    imagepath = `${basePath}${fileName}`;
  } else {
    imagepath = tour.imageCover;
  }

【讨论】:

    猜你喜欢
    • 2018-08-01
    • 2021-06-28
    • 2018-11-10
    • 1970-01-01
    • 1970-01-01
    • 2018-05-25
    • 2020-12-01
    • 2019-02-04
    相关资源
    最近更新 更多