Cypress: cy.request(): Got a broken PDF file

Created on 24 Feb 2019  Â·  9Comments  Â·  Source: cypress-io/cypress

Current behavior:

When I tried to use cy.request() API to get content of PDF file, I end up with broken file content.

Example of spec file:

/// <reference types="Cypress" />

context('Download Pdf', () => {

    it('Download Pdf', () => {
        const pdfUrl = 'http://www.pdf995.com/samples/pdf.pdf';

        cy.request({ url: pdfUrl, gzip: false})
            .then((response) => {
                const fileName = 'test';
                const filePath = 'temp/' + fileName + '.pdf';

                cy.writeFile(filePath, response.body, 'binary');
            });

    });
});

As a result, I have got PDF file with blank pages:

test.pdf

Which is not really what I try to download:

http://www.pdf995.com/samples/pdf.pdf

Desired behavior:

I want to get exactly the same file that I would get if use browser to download it.

Steps to reproduce: (app code and test code)

  1. Inited Cypress project
  2. Removed examples
  3. Create cypress/integration/sample/download-pdf.spec.js file and put there a snippet from Current behavior section.
  4. Create temp directory in the root directory of the project
  5. Open cypress
  6. Run download-pdf.spec.js in GUI
  7. Compare downloaded temp/test.pdf file with source one: http://www.pdf995.com/samples/pdf.pdf

Versions

  • OS: macOS HighSierra, v.10.13.3
  • NodeJs: v11.6.0
  • Cypress: Version 3.1.5 (3.1.5)
  • Running Chrome 72

Related Issues

bug

Most helpful comment

Yeah, this is reproducible from the code given above.

All 9 comments

This same on Windows

Yeah, this is reproducible from the code given above.

Hi

Same here. Is there any updates on this issue?
I'm checking #2029, i hope that workaround works:S
I need to save the pdf file, no further steps.

Thanks,
Turul

If anyone step into this river, the workaround in #2029 works (pdf).

Hi there,
You could try to set header of the response to 'Content-Type' : 'application/pdf' probably. This is for example possible with cy.route where you can provide 'headers: { 'Content-Type': 'application/pdf' } as an Object. This helped me with incorrect display of pdf as sometimes by default type is 'text/plain'

I'm facing the same issue as well… any updates?

I'm currently working on a fix proposal for this problem. The changes to cypress core would be:

  • Support of boolean option encodeBodyToBase64 to cy.request() options argument which would mean that the body of the response will be encoded to base64 at the stage of being a buffer/Uint8Array through buffer.toString('base64').

    This will ensure safe buffer transformation to base64, which can be quite useful for non-text responses. For example: in case response is an image, it can be directly used for data urls: data:text/plain;base64,IMAGE_RESPONSE_BODY_AS_BASE64.

  • Support of boolean option decodeContentFromBase64 to cy.writeFile() options argument which would mean that the content value passed should be treated as base64-encoded value, i.e: should be decoded throught buffer.from(base64Data, 'base64') before writing to file.

    This will be useful as data in cypress is are safer to transfer as strings from client to cypress server. So user can safely write binary content to file through cy.writeFile().

I finished the implementation of the fix itself and ensured that it is working locally. Even though, I still need to write tests before creating 2 proposal PRs to cypress-io/cypress and cypress-io/request repositories.


After the fix proposal, a working example would be:

/// <reference types="Cypress" />

context('Download Pdf', () => {
  it('Download Pdf', () => {
    const pdfUrl = 'http://www.pdf995.com/samples/pdf.pdf';

    // ADDED: "encodeBodyToBase64: true"
    cy.request({ url: pdfUrl, gzip: false, encodeBodyToBase64: true }).then(
      (response) => {
        const fileName = 'test';
        const filePath = 'temp/' + fileName + '.pdf';

        cy.writeFile(filePath, response.body, {
          encoding: 'binary',
          decodeContentFromBase64: true, // ADDED
        });
      }
    );
  });
});

I.e: setting the flag encodeBodyToBase64: true in cy.request() and decodeContentFromBase64: true in cy.writeFile()

The code for this is done in cypress-io/cypress#7382, but has yet to be released.
We'll update this issue and reference the changelog when it's released.

Released in 4.7.0.

This comment thread has been locked. If you are still experiencing this issue after upgrading to
Cypress v4.7.0, please open a new issue.

Was this page helpful?
0 / 5 - 0 ratings