Как вернуть PDF файл из контроллера - PullRequest
0 голосов
/ 27 ноября 2018

Я пытаюсь вернуть PDF-файл из конечной точки контроллера, используя NestJs.Если заголовок Content-type не задан, данные, возвращаемые getDocumentFile, возвращаются пользователю очень хорошо.Однако, когда я добавляю заголовок, получаемый ответ кажется странной формой GUID, ответ всегда выглядит так: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, где x - шестнадцатеричный символ в нижнем регистре.Похоже, что он совершенно не связан с фактическим возвращаемым значением функции-обработчика, поскольку я даже получаю эту странную GUID, когда вообще ничего не возвращаю.

Если не установить Content-type: application/pdf, функция возвращаетданные из буфера просто отлично, однако мне нужно установить заголовок, чтобы браузер распознал ответ как файл PDF, что важно для моего варианта использования.

Контроллер выглядит следующим образом:

@Controller('documents')
export class DocumentsController {
  constructor(private documentsService: DocumentsService) {}

  @Get(':id/file')
  @Header('Content-type', 'application/pdf')
  async getDocumentFile(@Param('id') id: string): Promise<Buffer> {
    const document = await this.documentsService.byId(id)
    const pdf = await this.documentsService.getFile(document)

    // using ReadableStreamBuffer as suggested by contributor
    const stream = new ReadableStreamBuffer({
      frequency: 10,
      chunkSize: 2048,
    })
    stream.put(pdf)
    return stream
  }
}

и мой DocumentService, подобный этому:

@Injectable()
export class DocumentsService {
  async getAll(): Promise<Array<DocumentDocument>> {
    return DocumentModel.find({})
  }

  async byId(id: string): Promise<DocumentDocument> {
    return DocumentModel.findOne({ _id: id })
  }

  async getFile(document: DocumentDocument): Promise<Buffer> {
    const filename = document.filename
    const filepath = path.join(__dirname, '..', '..', '..', '..', '..', 'pdf-generator', 'dist', filename)

    const pdf = await new Promise<Buffer>((resolve, reject) => {
      fs.readFile(filepath, {}, (err, data) => {
        if (err) reject(err)
        else resolve(data)
      })
    })
    return pdf
  }
}

Первоначально я только что возвратил буфер (return pdf), но это принесло тот же результат, что и попытка выше.В хранилище NestJs пользователь предложил использовать вышеуказанный метод, который, очевидно, тоже не работает для меня.Смотрите тему GitHub здесь .

1 Ответ

0 голосов
/ 30 ноября 2018

Это работает для меня.

@Get('pdf')
@HttpCode(HttpStatus.OK)
@Header('Content-Type', 'application/pdf')
@Header('Content-Disposition', 'attachment; filename=test.pdf')
pdf() {
    return createReadStream('./nodejs.pdf');
}

Кстати, я думаю, что было бы лучше использовать Stream вместо readFile.Потому что он загружает все содержимое файла в оперативную память.

...