0

I have problem when I run script it can download zip file but when open zip file it show error "The archive is either in unknow format or damaged"

Before write this script I try Webservice in Postman and use save responce "save to a file " i can get zip file and can use it

This is my code

javascript:

<a id="download-link" style="display: none;">Download</a>

<button id="get-token-button">Get OAuth 2.0 Token</button>

<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>

<script>

    $("#get-token-button").click(function() {
      $.ajax({
        url: "https://localhost:9445/test-org/api-test/oauth-test-provider/oauth2/token",
        type: "POST",
        data: {
          grant_type: "client_credentials",
          client_id: "client_id",
          client_secret: "client_secret",
          scope: "scope"
        },
        success: function(response) {       
          alert("Token: " + response.access_token);
          $.ajax({
        url: "https://localhost:9445/test-org/api-test/API/v1/ReceiptService/getReceiptByDataDate",
        type: "POST",
        headers: {
          "Authorization": "Bearer " + response.access_token
        },
        data: JSON.stringify({
          "dataDate": "Date",
          "ogaTaxNum": "TaxNum"
        }),
        contentType: "application/json",
        responseType: "arraybuffer",
        success: function(response) {
          alert(response);
          // If the request is successful, create a blob from the response and create a download link
          var blob = new Blob([response], {type: "application/zip"});
          var url = window.URL.createObjectURL(blob);
          $("#download-link").attr("href", url);
          $("#download-link").attr("download", "file.zip");
          $("#download-link").show();
        },
        error: function(jqXHR, textStatus, errorThrown) {
          // If the request fails, display an error message
          alert("Download failed: " + errorThrown);
        }
      });
    },
    error: function(jqXHR, textStatus, errorThrown) {
      // If the request fails, display an error message
      alert("Token request failed: " + errorThrown);
        }
      });
    });
  </script>

I want solution how to download zip file

Mariel
  • 3
  • 2
  • 3
    Not directly related to your problem, but: `client_secret: "916dc0d66"` - that value should never be exposed in publicly available client-side code in the first place. You are definitively doing things wrong here at the moment. – CBroe May 10 '23 at 09:23
  • @CBroe Thank you for advice I will change it, But value I random value and show for example in my code – Mariel May 11 '23 at 01:57
  • What do you get from `console.log(typeof response)`? – qrsngky May 11 '23 at 02:02
  • @qrsngky I get `PK|NoU� g�V�:)CUSTOMS_RECEIPT_20221115_202211150951.txtUT ��rc��rcux�d��n�6���>�����9�z(�hR�e�2^,�zM�k����|����by���D��8�l�0PH��̎4�p�5Dg?��=������ο��,#��17_P���H�.����H|0���:(�Jy��j�P�gJ����O՟�TF��b|2�t9_LG�u1Y�><̯��e�ɏ0}"�Vϗ���vZ|�e�er��&T�/�_��+�{��.�g�ߊ?��b<�/#��c0�ƶZ-4"�b�>���W�g�_��������ɟ�7 a�8 a�rye�@���X���5t�ǥ="�I��?w����q�g1@�R��e2Q&cn�i��WT���x�Kmܠ�_��V�����%�Fʐ4+�Ȕ�,���<���!�t-!��!�!'�9ӄr?gО�3I9��f�Ѵ2J-5-4��mH3I�qS��4J�Cy^���85�oHs`H����)N���k�U��[jZ�Ic� inH�c#�AK���:�.t��t�-h �̏6�ɫpU�,5-��jc-�T(�D��",��` – Mariel May 11 '23 at 02:25
  • `�` (0xfffd) is a sign that it tried to interpret your data as utf8 even though it was not, and the result is corrupted. Your `response` is a string which means your `responseType: "arraybuffer"` has no effect (I don't think jQuery even supports that option?). Try adding `mimeType: 'text/plain; charset=latin1'`. And even after that, you cannot directly use the string to make a blob. You need to map it using charCodeAt, like `var blob = new Blob([Uint8Array.from(response, a => a.charCodeAt(0))], { type: "application/zip" });` – qrsngky May 11 '23 at 02:49
  • @qrsngky ''mimeType: 'text/plain; charset=latin1' it add below 'responseType: "arraybuffer"' or instead of 'responseType: "arraybuffer"' – Mariel May 11 '23 at 03:34
  • Try adding below it first – qrsngky May 11 '23 at 03:37
  • @qrsngky I try adding below and change from `var blob = new Blob([response], {type: "application/zip"});` to `var blob = new Blob([Uint8Array.from(response, a => a.charCodeAt(0))], {type: "application/zip"});` after download and upzip zip file it show error `The archive is corrupt` I'm not sure it is have effective , text file in zip it have thai language – Mariel May 11 '23 at 03:47
  • Sorry, I found that `latin1` corrupts some bytes. You should use this instead: `mimeType: 'text/plain; charset=x-user-defined'` – qrsngky May 11 '23 at 04:11
  • @qrsngky Thank you for recommendation, Now I can download and unzip file correctly – Mariel May 11 '23 at 06:11
  • I think `responseType: "arraybuffer"` can be removed as it serves no purpose? (I know it's used in XMLHttpRequest, not sure if $.ajax supports it) – qrsngky May 11 '23 at 06:20

1 Answers1

0

The response is a string in this case. By default, it tries to interpret the response as UTF8, which is likely to corrupt some data (as the source data is binary). To prevent corrupting the data this way, you can add mimeType: 'text/plain; charset=x-user-defined' to the ajax settings.

Also, when creating a blob, the characters in the string should be mapped to values from 0 to 255, which can be done by Uint8Array.from(response, a => a.charCodeAt(0)). So, you can create the blob like this:

var blob = new Blob([Uint8Array.from(response, a => a.charCodeAt(0))], {type: "application/zip"});

EDIT: As I was searching for ways to avoid the old x-user-defined trick I came across another thread. So, with jQuery 3 it is possible to avoid it entirely using:

xhrFields: {responseType: 'blob'}

in the settings and the response can be used the following way:

var url = window.URL.createObjectURL(response);

Here, you don't even have to manually create the blob anymore as the response is already a blob.

Another answer to that thread shows you how to set it to blob only for successful response, by changing the xhr: setting.

qrsngky
  • 2,263
  • 2
  • 13
  • 10