javascript - React - API Yanıt Gövdesinden Bayt Dizisi Olarak Zip Dosyası İndirme?


Çalışan bir API çağrım var ve bu çağrı, Python tarafında Bytes formatında hazırlanmış ve zip dosyası olan bir string'i yanıt gövdesinde döndürüyor. String şu şekilde görünüyor, ama daha uzun: PK��Q��F���������������/export_file.csv��uX\M�

Bu, içinde bir csv dosyası bulunan bir zip dosyasıdır. Postman gibi araçlarda, aynı POST uç noktasına aynı parametrelerle istek gönderdiğimde, geçerli bir zip dosyasını başarıyla indirip içeriğini açabiliyor ve .csv dosyasını görebiliyorum. Tarayıcı hata ayıklayıcı araçlarında, API uç noktasının başarılı bir yanıt döndürdüğünü ve gövdede yukarıdaki aynı dizeyi gördüğümü görebiliyorum.

Her girişimde başarısız olduğum yer, bu dizeyi alıp aynı zip dosyasını indirmek için gerekli çalışmayı yapmakta react tarafıdır. SO’da ve başka yerlerde okuduğum her öneri bana başarısız oldu. İşte başarısız denemelerimin bazıları şöyle görünüyor:

(Ayrıca başarılı bir API çağrısının bu örnekten 26kb boyutunda bir yük döndürdüğünü unutmayın)

export function downloadZipFile(responseBody){

  /* Blob Attempts */

  // These download a 46kb file. Attempting to open gives "The compressed zip folder is invalid"
  // var blob = new Blob([responseBody], {type: "content-type"}); 
  // var blob = new Blob([responseBody], {type: "application/zip"}); 
  // var blob = new Blob([responseBody], {type: "application/zip, application/octet-stream"}); 
  // var blob = new Blob([responseBody], {type: "application/octet-stream"}); 
  // var blob = new Blob([responseBody], {type: "octet/stream"}); 

  var fileName = "export.zip";
  saveAs(blob,fileName);


  /* Data String Attempts */

  // const dataStr = "data:application/zip;" + responseBody; // "Failed - Network Error"
  // const dataStr = "data:application/zip, application/octet-stream;" + responseBody; // Downloads 1kb File "The compressed zip folder is invalid"
  // const dataStr = "data:application/zip,application/octet-stream;" + responseBody; // Downloads 1kb File "The compressed zip folder is invalid"
  // const dataStr = "data:application/octet-stream;" + responseBody; // "Failed - Network Error"

  let downloadElement = document.createElement('a');
  downloadElement.setAttribute("href", dataStr);
  downloadElement.setAttribute("download", "export.zip");
  document.body.appendChild(downloadElement); 
  downloadElement.click();
  downloadElement.remove();

}

Cevap #1

Geç geldim ama birine yardımcı olmayı umuyorum.

API çağrısında responseType'ı 'arraybuffer' olarak ayarlamak gerçekten önemlidir, şöyle:

...
export const getZip = async (id) => {
   const { data } = await axios.get(
      "/sypa-applications/export",
      {
        id
      },
      { responseType: "arraybuffer" } 
      );

   return data;
 }
 ...

Sonra ZIP dosyasını her iki yoldan da indirebilirsiniz:

1.- file-saver npm bağımlılığını kullanarak:

   let blob = new Blob([data], { type: "application/zip" });
   saveAs(blob, "fileName.zip");

2.- DOM Kullanarak:

const url = window.URL.createObjectURL(new Blob([data], { type: "application/zip" });
const link = document.createElement("a");
link.href = url;
link.setAttribute("download", "fileName.zip");
document.body.appendChild(link);
link.click();
link.parentNode.removeChild(link);

GET isteğinde responseType parametresini "arraybuffer" olarak ayarlayana kadar ZIP dosyasını indiremiyordum.

En iyi dileklerimle, Alberto.

Cevap #2

Bu aracı kontrol ettin mi? https://gildas-lormeau.github.io/zip.js/ Tarayıcıda js kullanarak bir dosyayı açma örneği var. http://gildas-lormeau.github.io/zip.js/demos/demo2.html

Görünüşe göre bu istediğiniz şey. Önce dosyanın sıkıştırmasını açın ve ardından .csv dosyasını istenildiği gibi kullanın