I have a fetch() request returning a Response object that is either a zip file (blob) or a JSON if there was an error with the request. The code I have successfully processes the zip file and sends it to the users Downloads folder. When a JSON response is returned, the code creates a empty/corrupt zip file.
How would I go about conditionally processing the Response object so that it prevents a file from being downloaded if it is a JSON? I would also like to store Response.json() in a variable?
await fetch(params)
.then(res => res.blob())
.then(blob => {
let url = window.URL.createObjectURL(blob);
let a = document.createElement('a');
a.href = url;
a.download = name + ".zip";
document.body.appendChild(a);
a.click();
a.remove(); //afterwards we remove the element
}).catch(err => console.error(err));
Thanks for the suggestions all. Per #Barmer and #Bergi suggestions I was able to redefine the API so that my error content is now just inside of a header. The solution I found looks like this:
await fetch(params)
.then(function(response) {
if (response.headers.get('X-Error') == 'False') {
return response.blob()
.then(blob => {
let url = window.URL.createObjectURL(blob);
let a = document.createElement('a');
a.href = url;
a.download = name + ".zip";
document.body.appendChild(a);
a.click();
a.remove();
}).catch(err => console.error(err))
}
//process error from backend
console.log(response.headers.get('X-Error'))
})
Related
Im using deep AI API to make an image a cartoon
await deepai.renderResultIntoElement(result, document.getElementById('RES'));
})();
How can I save that file as well as it be displayed in a RES div?
it renderes fine even with updates!
UPDATE:
await deepai.renderResultIntoElement(result, document.getElementById('RES'));
let e=await fetch(result, {
method: 'GET',
headers: {
'Content-Type': 'image',
},
});
let blob=await e.blob();
let url=window.URL.createObjectURL(blob);
let a=document.createElement('a');
a.href=url;
a.download='cartoon.jpeg'; //here goes file name
document.body.appendChild(a);
a.click();
sleep(100);
a.remove();
})()
I also tried let Blob=await response.blob();
that didnt work it just stopped it rendering!
Its nearly there its trying to download to a file but it is saying not correct format upon opening. any ideas?
I managed to get output file by sending GET request to url from result of callStandardApi method.
From that I get image response.
Then I download it as a file with hard coded name using this solution.
let e = await fetch(result.output_url, {
method: 'GET',
headers: {
'Content-Type': 'image/jpeg',
},
});
let blob = await e.blob();
let url = window.URL.createObjectURL(blob);
let a = document.createElement('a');
a.href = url;
a.download = 'filename.jpeg'; //here goes file name
document.body.appendChild(a);
a.click();
a.remove();
I am able to send a single image file to ReactJS. But I have to send multiple image files to ReactJS.
JAXRS code:
#GET
#Path("/download/file1")
#Produces( MediaType.APPLICATION_OCTET_STREAM )
public Response getFile() {
String fileName = DOWNLOAD_FILE_SERVER+"BMI/testcases/Basispath_BMI_0_out.gif";
File file = new File( fileName);
System.out.println("fileName inside getFile = "+fileName);
final String filename = "testcase1.gif";
System.out.println("filename inside getFile = "+filename);
// Create the JAXRS response
// Don't forget to include the filename in 2 HTTP headers:
//
// a) The standard 'Content-Disposition' one, and
// b) The custom 'X-Suggested-Filename'
final Response.ResponseBuilder builder = Response.ok(
file, MediaType.APPLICATION_OCTET_STREAM)
.header("X-Actual-Content-Length", file.length())
.header("Content-Disposition", "attachment; filename=\"" + file.getName() + "\"");
// All Done.
return builder.build();
}
ReactJS code:
downloadImage = () => {
axios({
url: 'http://localhost:9900/EXAMPLE/rest/myresource/download/file1',
method: 'GET',
responseType: 'blob',
}).then((response) => {
const url = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement('a');
link.href = url;
var filename = 'Image1.gif'
link.setAttribute('download', filename);
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
})
.catch((response) => { // then print response status
console.log("response = ",response);
})
}
Questions:
Is it possible to send multiple image files in the response of JAXRS?
How to receive multiple files in ReactJS GET response?
How to display received files in ReactJS?
Please provide solution to this issue.
I'm working on a project with Vue.js and Typescript for front-end and Java Spring as backend.
My java controller retrieves a given report from the db and then copies it into the HTML response.
I want the CSV to be downloaded by the browser therefore I added Content-disposition header in the response.
#GetMapping('/download')
public void downloadCSV(HttpServletRequest response){
Report r = reportService.findById(85);
response.addHeader("Content-Disposition", "attachment; filename=myCSV.csv");
response.setContentType("text/csv");
try {
InputStream stream = new ByteArrayInputStream(r.getDocument());
IOUtils.copy(stream, response.getOutputStream());
response.flushBuffer();
} catch(Exception e) {...}
}
I have 2 buttons: one simple hyperlink tag with href linking to download(), and a b-button (from bootstrap-vue) that once cliccked triggers download2().
<a :href="download" role="button"> Download CSV </a>
<b-button #click="event => download2()">
Download CSV v2
</b-button>
get download(): string {
return 'http://localhost:8080/download';
}
async download2() {
const rHeaders = new Headers();
rHeaders.append('Accept', 'text/csv');
const configInit = RequestInit = {
method: 'GET',
headers: rHeaders
};
try {
const res = await fetch('http://localhost:8080/download', configInit);
return res.text();
} catch (e) {...}
}
Now, If I click on the first button "Download csv", the csv is correctly downloaded by the browser. The javascript console prints the following:
Resource interpreted as Document but transferred with MIME type text/csv
and there is nothing in the response body.
Instead, if I click the 2nd button "Download csv v2", the download does not start but I have the csv in the response body.
Here, the differences in the request headers between the two.
*Header* *Download csv* *Download csv v2*
Sec-Fetch-Dest document empty
Sec-Fetch-Mode navigate cors
Sec-Fetch-User ?1 -
Upgrade-Insecure-Requests 1 -
the other headers are the same. It is not possible to change these headers, even if I set them in the javascript method; they remain still the same.
What's the problem?
Thank you.
I found a solution by "mimicking" the behavior of a <a> element:
This way, it works properly:
async download2() {
const configInit: RequestInit = {
method: 'GET'
};
try {
await fetch('http://localhost:8080/download', configInit)
.then(response => response.blob())
.then(blob => {
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
a.download = 'report.csv';
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
})
} catch (e) {...}
I have below functionality using JavaScript
The back end gives me a URL to download a file from like below -
https://something.org/FILENAME.ZIP
So I file name is fixed as FILENAME.ZIP
But while downloading a file , the file should get downloaded with custom file name like CUSTOMFILENAME.ZIP instead of FILENAME.ZIP
So,
1)The file should get downloaded from URL : https://something.org/FILENAME.ZIP
2)But it should get saved with different file name as :
CUSTOMFILENAME.ZIP
3)I have tried below programme from url - how to download a file from url using javascript or jquery?
var a = document.createElement("a");
a.href = url;
var fileName = CUSTOMFILENAME;
a.download = fileName;
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
a.remove();
But still file gets downloaded with whatever file name mentioned in URL
Can anybody please help me here ?
The file should get saved with CUSTOMFILENAME I provide and not fileName specified as part of URL
Try this see if it works,
const documentName = "CustomFileName"; // here your file name
fetch("http://yourdomain.com")
.then(res => {
return res.blob();
})
.then(blob => {
const href = window.URL.createObjectURL(blob);
const a = document.createElement("a");
a.download = documentName;
a.href = href;
a.click();
a.href = "";
})
.catch(err => console.error(err));
you are giving a object as download name give a string
I have a script to download different type files from server side. The code works for text/xml but when the downloaded pdf file is empty.
let response = this.http.get(this.Url , new Headers({responseType: 'blob'}))
.subscribe(doc => {
if (doc) {
let contentType = doc.headers.get("Content-Type");
let name = doc.headers.get("Content-Disposition").split("=")[1];
let blob = new Blob([doc.text()], {type: contentType});
let a = window.document.createElement("a");
a.href = window.URL.createObjectURL(blob);
a.download = name;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}
},
error => this.msgService.showError(this.msgs, error));
My server
#GET
#Consumes(MediaType.APPLICATION_JSON)
#Path("-----")
public Response getDocument(#PathParam("documentId") Long documentId) throws Exception {
Document document = ---------------;
return ResponseHelper.createOkResponse(
output -> IOUtils.write(document.documentContent(), output),
document.documentName(),
document.documentType()
);
}
I can see the doc.text() is returning some byte[]. Also tried {responseType: 'arraybuffer'}. can anyone advise how can i display for pdf ?
Thanks