skip to Main Content

I have created a utility function which is supposed to be common for all the api requests in node.js express app.

function axiosCall(method, endpoint, body) {
    let requestConfig = {
        url: encodeURI(`${endpoint.host}:${endpoint.port}${endpoint.path}`),
        method: method,  //can be POST, GET, etc
        proxy: false,
        data: body,
        headers: {
            "x-access-token": token,
            "X-Correlation-ID": correlationId,
            "Content-Type": "application/json"
        },
    }
    axios.request(requestConfig).then(response => {
        return response.data;
    }).catch((errorRes) => {
        throw { 
            error: errorRes.message, status: errorRes?.response?.status || 500, 
            responseContent: errorRes?.response?.data || "Server Error" 
        };
    })
}

it works fine for JSON responses, but does not give proper result for files, such as pdf.

the response which i got for a pdf file was like

{
    "status": 200,
    "statusText": "OK",
    "headers": {
      "server": "nginx/1.16.1",
      "date": "Fri, 02 Sep 2022 07:39:44 GMT",
      "content-type": "application/pdf",
      "content-length": "47658",
      "connection": "close",
    },
    "config": {...},
    "request": {...},
    "data": "%PDF-1.4rn%����rn1 0 objrn<<rn/Type /Catalogrn/Pages 2 0 Rrn/AcroForm 3 0 Rrn>>rnendobjrn4 0 objrn<<rn/�����M��0u0010��B�C������u0016�@?���`��u0003�N���u0012���~�L��u001e| O2�y3���;�fP�o�u0013u000e�Ҹ�c��}����E�VuSr�W��Vv�h�>=�u0001oGwi�j�⯰�u000f����=�,��5��]��g{�ŧ{���rݠu0012u0000U�%��Vv��rUL5�cu001d���1u000fu0015�'�u001fu001d*M��jk컲B_�+N�U�$u0019u0004�-L"t��u0001�s���Z��t�*MA����u0005a���h�4O�u0006�)H�9bm�ju0001BkX-Ah-+��i�wm@hu0017�� �KV{u0010�r�u0003b햔I@hw��a�嶍u0006�=��@Xp^��cu0016ܣ1 ,4+N�Xp^!#a���X�u0005�c8Ob�Il薑:IC�᭟oJ�u001e�3����އy�t�Au001aG�q(C޵�X��7��u0000�t��rnendstreamrnendobjrn26 0 objrn<<rn/Type /Fontrn/Subtype /CIDFontType2rn/BaseFont /GBMOJY+SymbolMTrn/CIDToGIDMap /Identityrn/DW 1000rn/FontDescriptor 31 0 Rrn/CIDSystemInfo <<rn/Registry (Adobe)rn/Ordering (Identity)rn/Supplement 0rn>>rnrn/W [120 [459]]rn>>rnendobjrn27 0 objrn<<rn/Filter /FlateDecodern/Length 225rn>>rnstreamrnx^m�ϊ�0u0010��u001c� �^�Pn�"����u0000i2-��$L�C�~�Tu0014u0016u000fu0019u0018~�r_F��sE6��a�kf�Z2��u001bY#4�Yu0012�u001du0018�u0003,]��W>u00133]OC����AQ���tb<��øu0006��r17~��0CM`u001f��+��W�la��B��6u000f��6l�$�֥�n��J�K���S[~ݤ�u0003�5�]}ր����TV���ճG��Di���xQa� ?�K��r�����ސmT�}q��Ԙ��u0019�֕�u0018c�u0001�u001a|/}!��qfJў<y��u0007c��ytu001cb ks]v]Fmz弦ou0019����u�v_�|�[_F>�G�w�m:n��.�m$�ZҨ�F-i�u0014〯�ou001c�u00120fJu0012`��Oz��{rP�vu0011u0004�}�����u001d�u0016�L\�u000b�u001d�n�C]�I�����MZ�~۷��Iu��u0014�6o�?�����W��ꡦ@?ZXG��wL�u0007���Gt���3�Y���DFl�����R� 34rn>>rnrnstartxrefrn46886rn%%EOFrn"
}

I am unable to convert this response.data to pdf file.

Then i read about setting responseType: "arraybuffer", which gave the buffer[] and I can use it in code to generate the file. but on setting the responseType, the error was also of buffer type instead of json. which again required further processing to convert it to json format.

so, is there a way to get pdf file from axios, by converting the response.data, which I received with default responseType.

or can we set responseType dynamically after getting response from the server, as i get the content-type in headers. so as to make a utility function which can work with all kinds of responses.

2

Answers


  1. Chosen as BEST ANSWER

    As I didn't get a proper resolution i handled it manually by passing a flag to the axios utility function.

    const customObjectify = (data) => {
        try {
            if(typeof data === "string"){
                JSON.parse(data);
            }
            return data;
        } catch (error) {
            return data;
        }
    }
    

    main block is below

    //adding a default value false to parameter, so i don't need to change at all function calls.
    function axiosCall(method, endpoint, body, isFileInResponse= false) {
        let requestConfig = {
            url: encodeURI(`${endpoint.host}:${endpoint.port}${endpoint.path}`),
            method: method,  //can be POST, GET, etc
            proxy: false,
            data: body,
            headers: {
                "x-access-token": token,
                "X-Correlation-ID": correlationId,
                "Content-Type": "application/json"
            },
        }
        if(isFileInResponse){
             requestConfig.responseType = "arraybuffer";
        }
        axios.request(requestConfig).then(response => {
            return response.data;
        }).catch((errorRes) => {
        try {
              let responseContent;
              if(isFileInResponse) {
                 // arraybuffer error needs to be converted to json
                  responseContent = customObjectify(errorRes.response.data.toString());
              } else {
                  responseContent = errorRes.response.data;
              }
              throw ({ error: errorRes.message, status: errorRes?.response?.status || 500, responseContent});
        } catch (error) {
             throw ({ error: errorRes.message, status: errorRes?.response?.status || 500, responseContent: "Server Error" });
        }
        throw { 
                error: errorRes.message, status: errorRes?.response?.status || 500, 
                responseContent: errorRes?.response?.data || "Server Error" 
            };
        })
    }
    

  2. As mentioned in this question (https://stackoverflow.com/a/53230807/19179818) you could put code in your .then() to create an anchor tag on your page and click it automatically to download the file, and delete the tag afterwards. (posted as awnser instead of comment because of not enough reputation)

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search