How to return PDF file from controller

Related searches

I try to return a PDF file from a Controller Endpoint using NestJs. When not setting the Content-type header, the data returned by getDocumentFile gets returned to the user just fine. When I add the header however, the return I get seems to be some strange form of a GUID, the response always looks like this: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx where x is a lowercase hexadecimal character. It also seems to be totally unrelated to the actual return value of the handler function, as I even get this strange GUID-thing when not returning anything at all.

When not setting Content-type: application/pdf, the function returns the data of the buffer just fine, however I need to set the header in order to get the browser to recognize the response as a PDF file which is important for my use case.

The controller looks like this:

@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
  }
}

and my DocumentsService like this:

@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
  }
}

I originally just returned the buffer (return pdf), but that brought the same result as the attempt above. On the repository of NestJs a user suggested to use the above method, which obviously does not work for me either. See the GitHub thread here.

It works for me.

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

BTW, I think it should be better to use Stream instead of readFile. Because it loads all contents of the file into RAM.

Return PDF in MVC, As far as I know, you can use the WebClient class to download the file from the remote url and then return it using the Controller.File method. Return a FileContentResult. The last line in your controller action would be something like: return File("Chap0101.pdf", "application/pdf"); If you are generating this PDF dynamically, it may be better to use a MemoryStream, and create the document in memory instead of saving to file.

I know this old thread. But it might help someone. similar to @Victor

  @Get('pdf')
  @HttpCode(201)
  @Header('Content-Type', 'image/pdf')
  @Header('Content-Disposition', 'attachment; filename=test.pdf')
  public pdf() {
    return fs.createReadStream('./test.pdf');
  }

How to Return Files From Web API, Open Visual Studio and create New Web API project. Create Book folder at root level in the project. Add any sample pdf, word, excel, zip (name them as sample) files into it. Create a new API controller and Copy the content of EbookController from the downloaded project into it. Return PDF(.pdf) file . Here we will be returning a PDF file from the Controller method. Using the below technique controller can return any other types of file as well like .doc or .txt etc. For PDF file we need to use mimeType = “application/pdf.

You can just use ready decorator @Res this is my working solution:

Controller(NestJs):

async getNewsPdfById(@Param() getNewsParams: GetNewsPdfParams, @Req() request: Request, @Res() response: Response): Promise<void> {
  const stream = await this.newsService.getNewsPdfById(getNewsParams.newsId, request.user.ownerId);

  response.set({
    'Content-Type': 'image/pdf',
  });

  stream.pipe(response);
}

In my case stream variable is just ready stream created by html-pdf library because i create pdf by html https://www.npmjs.com/package/html-pdf but it doesnt matter how you create your stream. The thing is that you should use @Res decorator and pipe it because its native NestJs solution.

Also here is code how to claim file on client side: https://gist.github.com/javilobo8/097c30a233786be52070986d8cdb1743

Anyway lets try this one in your case:

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

  @Get(':id/file')
  async getDocumentFile(@Param('id') id: string, @Res res: Response): Promise<Buffer> {
    const document = await this.documentsService.byId(id)
    const pdf = await this.documentsService.getFile(document)


    const stream = new ReadableStreamBuffer({
      frequency: 10,
      chunkSize: 2048,
    })

    res.set({
      'Content-Type': 'image/pdf',
    });

    stream.pipe(res);
  }
}

ASP.NET MVC Action Results and PDF Content, Want to serve a PDF file with dynamically-generated content? that takes the return value of a controller's action method down to the browser. How To Open PDF File In New Tab In MVC Using C#. Step 1. First, create a new project of MVC from File -> New -> Project. Step 2. Select ASP.NET Web Application (.Net Framework) for creating an MVC application and set Name and Location of Project. Step 3. After setting the name and location of the

Return Pdf document from Asp.net MVC controller, Just create pdf server side and return File instead of html view. I don't what kind of pdf provider do you use but this a solution for iTextSharp: How to return PDF to� I am supposed to acces an endpoint that returns a pdf file as response. How do I return the same pdf file to the user from my MVC controller so that it can be downloaded. I do not want to save it to the disk. Instead show it directly to the user.

B. Return file as a download. Sometimes, you need to return a file to be downloaded in your controller, therefore you need to use the BinaryFileResponse class, but you need to modify the disposition of the response and add the mimetype of the file that will be downloaded in the headers. This is perfect for files like PDFs, document files

In the DownloadPDFController we will create a default request mapping for the application. The return type will be a ResponseEntity, an extension of HttpEntity that adds a HttpStatus code, and will be of type InputStreamResource. Next for demonstration purposes we fetch a file named pdf-sample.pdf from the classpath by using ClassPathResource.

Comments
  • There is no error, but, as I described above, I don't get the PDF data as a return but a seemingly random GUID (which is different on every request, btw). No error message whatsoever, just not the result I want, obviously
  • did you find a solution?
  • Unfortunately not. Are you having the same problem?
  • not similar but i couldn't manage to download file from a React App using axios. All i'm getting is empty blob data or this output <Buffer 25 50 44 46 ... >
  • I copied your exact code (and replaced the filename, obviously) but the result is still the same... which version of Nest are you using?
  • i had to add .pipe(response) on the created read stream for it to work (and remove the Content-Disposition header)
  • Won't this lead to a download of the file? What I originally wanted was to display the pdf in the browser
  • Try to replace the attachment into inline. developer.mozilla.org/en-US/docs/Web/HTTP/Headers/…