javascript - Convertiți răspunsul ByteArray de la API într-un fișier în Typescript și salvați-l
Există deja câteva întrebări asemănătoare cu cea pe care o pun și am încercat acele abordări, dar nu au funcționat pentru mine, poate că îmi lipsește ceva și de aceea pun o întrebare nouă.
Apelez un API în aplicația mea TypeScript, API-ul îmi returnează un obiect care are un câmp ce conține reprezentarea sub formă de șir de octeți a unui fișier. Iată cum arată modelul răspunsului
{
"fileName": "Pokemon.xlsx",
"fileData":"this is the byte array representation of the file",
"fileContent":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
}
În componenta mea TypeScript apelez API-ul și convertesc răspunsul JSON într-o interfață de răspuns, acest cod dat este ceea ce am referit de la alte linkuri
this.pokemonService.getExcel(REQUEST_OBJECT).subscribe((response) => {
if (response) {
const bytes = new Uint8Array(Buffer.from(response.fileData));
const fileBlob = new Blob([bytes], { type: response.contentType });
if (fileBlob.size > 0) {
const link = document.createElement('a');
link.href = window.URL.createObjectURL(file);
link.download = `${response.fileName}`;
link.click();
}
} else {
//show error
}
});
dat este interfața de răspuns la care transform răspunsul
export interface PokemonResponse {
fileData: ArrayBuffer;
fileName: string;
contentType: string;
}
Problema cu codul de mai sus este că atunci când deschid Excel-ul, acesta arată că fișierul este corupt,
De asemenea, am încercat să convertesc fileBlob în codul de mai sus într-un obiect File folosind codul de mai jos, dar rezultatul a fost același; fișierul descărcat, atunci când este deschis cu Excel, apare ca fiind corupt.
const file = new File([bytes], response.fileName, { type: response.contentType });
Un lucru pe care îl observ este că ArrayBuffer conține o reprezentare sub formă de șir de caractere (presupun că este base64) a fișierului, în timp ce API-ul returnează un tablou de octeți.
Am încercat să apelez API-ul direct folosind o aplicație console C# și în aplicația console funcționează conform așteptărilor, fișierul Excel este creat și pot să-l deschid și să văd datele fără niciun avertisment de fișier corupt.
Simt că sunt aproape de soluție, dar îmi lipsește ceva aici în legătură cu ArrayBuffer. Vă rog să sugerați.
EDITARE: Adăugarea unui screenshot al comparației byte dintre aplicația C# console și aplicația TypeScript
Aplicație consolă:
și iată o prezentare a byte-ului pe care îl primesc în aplicația TypeScript, rețineți că afișez variabila bytes prezentată în codul de mai sus, care este un Uint8Array,
Observând ambele reprezentări în bytes, se pare că octeții nu sunt în aceeași secvență, cred că conversia Uint8Array ar putea perturba secvența în TypeScript.
Răspuns #1
După ce am petrecut ceva timp, am reușit să rezolv problema.
Am descoperit că trebuie să menționăm în mod explicit tipul de date pe care browserul trebuie să îl parseze și să îl returneze, așa că înainte de a returna răspunsul de la serviciu în Angular, am actualizat tipul de conținut cu următorul cod
contentType: `data:${response.contentType};base64,`
Vă rugăm să rețineți că contentType este o proprietate a interfeței PokemonResponse, așa cum este prezentat mai sus.
Odată ce am făcut acest lucru, fișierul a fost descărcat cu succes. Am presupus că acest lucru fusese deja făcut de browser, dar m-am înșelat.
Pentru referință, iată întregul cod pe care trebuie să-l folosesc pentru a descărca fișierul
axios.post<YOUR_RESPONSE_INTERFACE>('YOUR_API_ENDPOINT')
.then((response) => {
const updatedContentType = `data:${response.data.contentType};base64,`
const fileDownloadElement = document.createElement('a');
document.body.appendChild(fileDownloadElement);
fileDownloadElement.download = `${response.data.fileName}`;
fileDownloadElement.href = updatedContentType + response.data.fileData;
fileDownloadElement.setAttribute('style', 'display:none;');
fileDownloadElement.target = '_blank';
fileDownloadElement.click();
document.body.removeChild(fileDownloadElement);
})
.catch((error) => {
console.log(error);
})
Sper că ajută.



