1

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.4\r\n%����\r\n1 0 obj\r\n<<\r\n/Type /Catalog\r\n/Pages 2 0 R\r\n/AcroForm 3 0 R\r\n>>\r\nendobj\r\n4 0 obj\r\n<<\r\n/�����M��0\u0010��B�C������\u0016�@?���`��\u0003�N���\u0012���~�L��\u001e| O2�y3���;�fP�o�\u0013\u000e�Ҹ�c��}����E�VuS\r�W��Vv�h�>=�\u0001oGwi�j�⯰�\u000f����=�,��5��]��g{�ŧ{���\rݠ\u0012\u0000U�%��Vv��\rUL5�c\u001d���1\u000f\u0015�'�\u001f\u001d*M��jk컲B_�+N�U�$\u0019\u0004�-L\"t��\u0001�s���Z��\t�*MA����\u0005a���h�4O�\u0006�)H�9\bm�j\u0001BkX-Ah-+��i�wm@h\u0017�� �KV{\u0010�\r�\u0003\b햔I@hw��a�嶍\u0006�=��@Xp^��c\u0016ܣ1 ,4+N�Xp^!#a���X�\u0005�c8Ob�Il薑:IC�᭟oJ�\u001e�3����އy�\t�A\u001aG�q(C޵�X��7��\u0000�t��\r\nendstream\r\nendobj\r\n26 0 obj\r\n<<\r\n/Type /Font\r\n/Subtype /CIDFontType2\r\n/BaseFont /GBMOJY+SymbolMT\r\n/CIDToGIDMap /Identity\r\n/DW 1000\r\n/FontDescriptor 31 0 R\r\n/CIDSystemInfo <<\r\n/Registry (Adobe)\r\n/Ordering (Identity)\r\n/Supplement 0\r\n>>\r\n\r\n/W [120 [459]]\r\n>>\r\nendobj\r\n27 0 obj\r\n<<\r\n/Filter /FlateDecode\r\n/Length 225\r\n>>\r\nstream\r\nx^m�ϊ�0\u0010��\u001c� �^�P\n�\"����\u0000i2-��$L�C�~�T\u0014\u0016\u000f\u0019\u0018~�\r_F��sE6��a�k\f�Z2��\u001bY#4�Y\u0012�\u001d\u0018�\u0003,]��W>\u00133]OC����AQ���t\b<��ø\u0006��\r17~��0CM`\u001f��+��W�la��B��6\u000f��6l�$�֥�n��J�K���S[~ݤ�\u0003�5�]}ր����TV���ճG��Di���xQa� ?�K��\r�����ސmT�}q��Ԙ��\u0019�֕�\u0018c�\u0001�\u001a|/}!��qfJў<y��\u0007c��y\t\u001c\b ks]v]Fmz弦o\u0019����u�v_�|�[_F>�G�w�m:n��.�m$�ZҨ�F-i�\u0014〯�o\u001c�\u00120fJ\u0012`��Oz��{rP�v\u0011\u0004�}�����\u001d�\u0016�L\\�\u000b�\u001d�n�C]�I�����MZ�~۷��Iu��\u0014�6o�?�����W��ꡦ@?ZXG��wL�\u0007���G\t���3�Y���DFl�����R� 34\r\n>>\r\n\r\nstartxref\r\n46886\r\n%%EOF\r\n"
}

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.

Shubham Shaw
  • 841
  • 1
  • 11
  • 24

2 Answers2

0

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" 
        };
    })
}
Shubham Shaw
  • 841
  • 1
  • 11
  • 24
-1

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)

NekoLuka
  • 21
  • 4