Trying to download excel (.xlsx) file from my restAPI.
This is my code -
let headers = new Headers();
headers.append('Content-Type', 'application/vnd.openxmlformats');
this.http
.get(
`${pathToExcel}`,
{ headers: headers, responseType: ResponseContentType.Blob }
)
.subscribe((res: any) => {
let blob = new Blob([res._body], { type: 'application/vnd.openxmlformats' });
let myUrl = document.createElement('a');
myUrl.href = window.URL.createObjectURL(blob);
myUrl.download = 'Log.xlsx';
let event = document.createEvent('MouseEvent');
event.initEvent('click', true, true);
myUrl.dispatchEvent(event);
});
The file is downloaded but it's empty.
What am I missing?
Related
I'm trying to generate a xlsx file using SheetJS in node. Then in my frontend I have a button to call this route and download the file. Currently I have the following:
// backend code
export function exportExcel(req: Request, res: Response) {
try {
const workbook = utils.book_new();
const fileName = "sample";
const dataSheet = utils.json_to_sheet(sampleData);
utils.book_append_sheet(workbook, dataSheet, fileName.replace("/", ""));
const binaryWorkbook = write(workbook, {
type: "array",
bookType: "xlsx",
});
return res.status(OK).send(binaryWorkbook);
} catch (_error) {
return res.sendStatus(500)
}
}
Then in the front end I have the following:
const handleExcelExport = () => {
const { data } = await axios.get(
`/export-excel`,
{
responseType: "blob",
}
).then(response => {
const blob = new Blob([response], {
type: "application/octet-stream",
});
const link = document.createElement("a");
link.href = window.URL.createObjectURL(blob);
link.download = fileName;
link.click();
}
}
// I simply call the above in the onClick handler in a button
<button onClick={handleExcelExport}> Export excel </button>
I can see that a download file appears when I click on the button but I can't open it. MS Excel says that ""File format or file extension is not valid..."
I fixed by changing to the following in the BE:
const binaryWorkbook = write(workbook, {
type: "array",
bookType: "xlsx",
});
and also adding headers per the docs:
res.setHeader(
"Content-Disposition",
'attachment; filename="SheetJSNode.xlsx"'
);
res.setHeader("Content-Type", "application/vnd.ms-excel");
Then in the frontend I changed the response type and content-type to
{
responseType: "arraybuffer",
}
Blob content-type
const blob = new Blob([response], {
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
});
I am trying to open pdf from the cloud in a new tab, without downloading it to the local machine.
I tried this way but not working for me. In the new tab, it is giving an error.
function readFileInNewTab (fileId) {
let url = BASE_URL + "api/CMS/Documents/Download/" + fileId;
const requestOptions = {
method: 'GET',
headers: { 'Content-Type': 'application/pdf', ...authHeader(url) },
credentials: 'include',
responseType: "blob", // important
};
inProgress = true;
return fetch (url, requestOptions).then(handleResponse)
.then((response)=> {
const file = new Blob([response], { type: "application/pdf" });
//Build a URL from the file
const fileURL = URL.createObjectURL(file);
//Open the URL on new Window
const pdfWindow = window.open();
pdfWindow.location.href = fileURL;
})
.catch((error) => {
console.log(error);
});
}
I'm trying to upload a cropped image via client using fetch. The upload process works, the file size seems to be correct too but the uploaded image is corrupt and appears to be a white 16x16 square on the server. The file won't open when I download it (damaged or corrupt). I'm struggling to understand what I'm doing wrong. The back-end is Drupal.
Uploading files directly from an input using the same postFile function works without a problem.
const toFile = (blob) => {
blob.lastModifiedDate = new Date();
blob.name = 'cropped.png';
return blob;
}
const onCropperCrop = () => {
const imageElement = cropperRef?.current;
const cropper = imageElement?.cropper;
cropper.getCroppedCanvas().toBlob((blob) => {
const file = toFile(blob);
onCrop(file);
});
};
const onCrop = (file) => postFile(params);
export const postFile = async (
_file,
_uri,
_xcsrf_token,
_accessToken,
) => {
let formData = new FormData();
formData.append('File', _file);
let headers = {
headers: {
Accept: 'application/hal+json',
'Content-Type': 'application/octet-stream',
'Content-Disposition': 'file; filename="' + _file.name + '"',
'X-CSRF-Token': _xcsrf_token,
Authorization: 'Bearer ' + _accessToken,
},
};
return await fetch(_uri, {
method: 'POST',
headers: headers,
body: formData,
credentials: 'include'
});
};
The file object:
Flast is receiving ImmutableMultiDict([]).
My Html Code
const audioChunks = [];
mediaRecorder.addEventListener("dataavailable", event => {
audioChunks.push(event.data);
});
mediaRecorder.addEventListener("stop", () => {
const audioBlob = new Blob(audioChunks, { type: 'audio/wav' });
console.log(audioBlob)
var myHeaders = new Headers();
myHeaders.append("Content-Type", "audio/wave");
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: audioBlob,
redirect: 'follow'
};
My Flask Code
#app.route('/stt',methods=['GET','POST'])
def STT():
app.logger.warning("request.files: {0}".format(request.files))
f = request.files['audio-blob']
print(f)
file_obj = io.BytesIO() # create file-object
file_obj.write(f.read()) # write in file-object
file_obj.seek(0) # move to beginning so it will read from beginning
r = sr.Recognizer()
mic = sr.AudioFile(file_obj) # use file-object
with mic as source:
audio = r.record(source)
result = r.recognize_google(audio_data=audio, language="en-US", show_all=True)
return jsonify(text=result )
Not able to understand the error.
How to post Blob file from html and received in Flask Post APIs.
Please Help me out on this problem.
Thank You
I am sending a zip file from my nodejs server to the browser using the following
res.set("Content-Type", "application/octet-stream");
res.set("Content-disposition", `attachment; filename="`+zip_name+`.zip"`);
res.set("Content-Length", zipBuff.length);
res.send(zipBuff);
I am then fetching it by using :
fetch("/my/url", {
method: "POST",
body: formData,
})
.then(response => {
return response.blob();
})
.then(response => {
const blob = new Blob([response], {type: 'application/zip'});
const downloadUrl = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = downloadUrl;
a.download = "blah.zip";
document.body.appendChild(a);
a.click();
});
I would like to be able to use zip_name instead of blah for the filename but I can't figure out how to access the headers (in that case Content-disposition) of the response with fetch.
Could someone please explain how it's done ?
Return blob and headers in object
fetch("/my/url", {
method: "POST",
body: formData,
})
.then(response => {
const headers = response.headers
return { blob: response.blob(), headers }
})
.then(({blob, headers}) => {
/// now you can access to **headers** and blob data
});
UPD:
To access the headers use headers.get("Header name").split('=').pop()
UPD1:
const foo = async () => {
const response = await fetch("/my/url", {
method: "POST",
body: formData,
})
if(!response.ok)
thorw new Error("Some error happend")
const blod_data = await response.blob()
const header_with_name = response.headers.get("Header name").split('=').pop()
// do something with it
}
In the first promise arrow function you have access to the HTTP response headers. If you update it to return the promise from the blob function call. Then in this nested function you can return an object that includes the header value to the outer second arrow function that processes the blob data.
Updated fetch example that includes processing the Promise returned from blob-function call.
fetch("/my/url", {
method: "POST",
body: formData,
})
.then(response => {
return response.blob().then((data) => {
return {
data: data,
filename: response.headers.get('Content-disposition'),
};
});
})
.then(({ data, filename }) => {
const blob = new Blob([data], { type: 'application/zip' });
const downloadUrl = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = downloadUrl;
a.download = filename.split('=')[1];
document.body.appendChild(a);
a.click();
});
Thank you Chapo for pointing out the issue with my previous example