I have an Springboot rest controller to download a file. I am trying to access the endpoint using the browser and able to see the response in the xhr.response. However, i want to force the file download which i am not able to achieve.
The code is as follows :
Rest based endpoint (Springboot):
#GetMapping(value = "download/{id}", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE, consumes = "*/*")
public ResponseEntity<InputStreamResource> getFile(#PathVariable("id") Long contractId) {
Contract contract;
contract = this.contractRepository.findOne(contractId);
System.out.println(contract.getPath()); // test
InputStreamResource resource = null;
HttpHeaders respHeaders = new HttpHeaders();
if (contract != null) {
try {
File file = new File(contract.getPath());
FileInputStream fileInputStream = new FileInputStream(file);
resource = new InputStreamResource(fileInputStream);
System.out.println(resource.exists());//test
respHeaders.add("Content-Type", URLConnection.guessContentTypeFromStream(fileInputStream));
respHeaders.add("Cache-Control", "no-cache, no-store, must-revalidate");
respHeaders.add("Pragma", "no-cache");
respHeaders.add("Expires", "0");
respHeaders.add("Content-Disposition", "attachment;filename=" + file.getName());
respHeaders.add("Content-Transfer-Encoding", "Binary");
respHeaders.setContentLength(file.length());
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
return new ResponseEntity<InputStreamResource>(
this.companyService.downloadContract(contractId),
respHeaders,
HttpStatus.OK
);
}
My xhr request is as follows
var xhr = new XMLHttpRequest();
xhr.open("GET", http.getHRTargetURL() + "download/" + id, true);
xhr.setRequestHeader("X-Auth-Token", http.getToken());
xhr.setRequestHeader("Accept", "application/octet-stream");
xhr.setRequestHeader("Content-Type", "application/octet-stream");
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.response != "0") {
console.log(xhr)
console.log("Downloaded file");
} else {
console.log("error downloading document")
}
}
xhr.send();
I am able to get the response from the endpoint . I can see the file contents in the xhr response on the browser
My problem is how can I force this response to popup file save wizard on the browser.
You could try like this.
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.response != "0") {
console.log(xhr)
var windowUrl = window.URL || window.webkitURL;
var url = windowUrl.createObjectURL(xhr);
anchor.prop('href', url);
anchor.prop('download', "filename");
anchor.get(0).click();
windowUrl.revokeObjectURL(url);
console.log("Downloaded file");
} else {
console.log("error downloading document")
}
}
xhr.send();
Well as I figured out that problem was with the frontend and had nothing to do with backend as Springboot was sending the proper response back.
Building on the answer provided by Dinesh above i modified my answer as follows
download(id, name){
var xhr = new XMLHttpRequest();
xhr.open("GET", http.getHRTargetURL() + "download/" + id, true);
xhr.setRequestHeader("X-Auth-Token", http.getToken());
xhr.setRequestHeader("Content-Type", "application/octet-stream");
xhr.responseType = "blob";
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
var a = document.createElement("a");
document.body.appendChild(a);
a.style = "display: none";
var url = window.URL.createObjectURL(new Blob([xhr.response], {type: "octet/stream"}));
a.href = url;
a.download = name;
a.click();
window.URL.revokeObjectURL(url);
} else {
console.log("error downloading document")
}
}
xhr.send();
}
Related
I'm trying to program a Client, that can record audio data and then send it to a server.
I don't have much experience in front-end development. I was told to use React and so I'm trying to use ReactMediaRecorder (https://github.com/avasthaathraya/react-media-recorder).
render () {
return (
<ReactMediaRecorder
audio
whenStopped={blobUrl=>this.setState({audio: blobUrl })}
render={({startRecording, stopRecording, mediaBlob }) => (
<div>
<button id="recorder" className="button" onClick={startRecording}>Start Recording</button>
<button className="button" onClick={() => {stopRecording();this.upload()}}>Stop Recording</button>
<audio id="player" src={mediaBlob} controls />
</div>
)}
/>
)
}
upload() {
console.log("upload was called with blob " + this.state.audio)
//if (false) {
if (this.state.audio != null) {
console.log("got here, type of audio is " + this.state.audio)
var xhr = new XMLHttpRequest();
var filename = new Date().toISOString();
xhr.onload = function (e) {
if (this.readyState === 4) {
console.log("Server returned: ", e.target.responseText);
}
};
var fd = new FormData();
fd.append("audio_data", this.state.audio, filename);
xhr.open("POST", "http://127.0.0.1:3000", true);
xhr.send(fd);
}
}
At first it seemed very straightforward. But I don't get why I can't send the mediaBlob. The formData.append says, that this.state.audio is not of type Blob. So I checked it's type in the console log, and found out it is of type stringContent. I tried to create a Blob from that by using new Blob() but failed. I also fail to find information of this type.
Does somebody know what to do?
Ok I finally got it. The mistake was, that mediaBlob is actually not blob, but a blob Url. So first we need to load it and then we can send it. I changed my upload function to:
upload(mediaBlob) {
if (this.state.audio != null) {
//load blob
var xhr_get_audio = new XMLHttpRequest();
xhr_get_audio.open('GET', mediaBlob, true);
xhr_get_audio.responseType = 'blob';
xhr_get_audio.onload = function(e) {
if (this.status == 200) {
var blob = this.response;
//send the blob to the server
var xhr_send = new XMLHttpRequest();
var filename = new Date().toISOString();
xhr_get_audio.onload = function (e) {
if (this.readyState === 4) {
console.log("Server returned: ", e.target.responseText);
}
};
var fd = new FormData();
fd.append("audio_data",blob, filename);
xhr_send.open("POST", "http://localhost/uploadAudio",
true);
xhr_send.send(fd);
}
};
xhr_get_audio.send();
}
}
Now it works fine.
Hi I am new to java script, I am trying to download zip file from a web server running in http://10.1.2.137:5000/download.
When I access the URL alone in the browser as http://10.1.2.137:5000/download, te zip file is getting downloaded , but when I call from java script , the zip file is getting corrupted it seems. Not able to open the zip file with win rar.
Not sure this is the issue with CORS.
$scope.downloadData = function (){
console.log ('Entering in to Download Method')
var url = 'http://10.1.2.137:5000/download';
var xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xhr.setRequestHeader("Access-Control-Allow-Origin", "*");
xhr.responseType = "arraybuffer";
var linkElement = document.createElement('iframe');
document.body.appendChild(linkElement)
xhr.send();
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
var blob = new Blob([str2bytes(xhr.response)], {type: "application/zip"});
var fileName = "logs.zip";
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(blob, filename);
} else {
var a = document.createElement("a");
document.body.appendChild(a);
a.style = "display:none";
var url = window.URL.createObjectURL(blob);
a.href = url;
a.download = fileName;
a.click();
window.URL.revokeObjectURL(url);
a.remove();
}
}
}
};
You can use window.open, this will instruct the browser to open the url and start download. e.g.
window.open("http://10.1.2.137:5000/download","_self");
I use spring boot, jquery and itext.
When user click on a button, a pdf file is genereated.
#GetMapping(value = "/members/{memberId}/contract/{contractId}/generalcontracts", produces = "application/pdf")
public ResponseEntity<byte[]> getMemberContract(#PathVariable("memberId") Long memberId, #PathVariable("contractId") Long contractId) throws IOException {
byte[] content = reportService.generateMemberContractReport(contractId);
return prepareReport(content);
}
private ResponseEntity<byte[]> prepareReport(byte[] content) throws IOException {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.parseMediaType("application/pdf"));
String filename = "report.pdf";
headers.setContentDispositionFormData(filename, filename);
headers.setCacheControl("must-revalidate, post-check=0, pre-check=0");
ResponseEntity<byte[]> response = new ResponseEntity<>(content, headers, HttpStatus.OK);
return response;
}
A tab open and file is displayed.
That code work with chrome but not with firefox.
With firefox, it's like the tab open and close.
<button id="memberPrintReport" type="button" class="btn btn-primary">Imprimer</button>
$("#memberPrintReport").on('click', function (e) {
tryit(getHostName() + "/members/" + memberId + "/contract/" + contractId + "/generalcontracts");
}
function tryit(urlServer) {
var win = window.open('_blank');
downloadFile(urlServer, function (blob) {
var url = URL.createObjectURL(blob);
win.location = url;
});
}
function downloadFile(url, success) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.setRequestHeader("Authorization", "Basic " + $.cookie('authorization'));
xhr.responseType = "blob";
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (success)
success(xhr.response);
}
};
xhr.send(null);
}
function tryit(urlServer) {
downloadFile(urlServer, function (blob) {
var url = URL.createObjectURL(blob);
window.open(url, '_blank');
});
}
Try updating this line
headers.setContentDispositionFormData(filename, filename);
to this
headers.setContentDispositionFormData("inline", filename);
if this does not work then try this:
headers.add("content-disposition", "inline;filename=" + filename)
I'm downloading a file from cross-domain and its working both in chrome and Firefox but not working in safari. Both Chrome and Firefox are downloading where as Safari is playing the song. It's safari bug but solved by somebody and I didn't quite get it. Please do help me.
Note: Giving a small error : Failed to load resource: Frame load interrupted
Clientside code:
var url = "http://www.example.com/song.mp3";
var xhr = createCORSRequest('GET', url);
if (!xhr) {
alert('CORS not supported');
return;
}
xhr.responseType = 'blob';
xhr.onload = function() {
var a = document.createElement('a');
a.href = window.URL.createObjectURL(xhr.response);
a.download = 'FileName.mp3';
a.style.display = 'none';
document.body.appendChild(a);
a.click();
delete a;
};
xhr.onerror = function() {
alert('Woops, there was an error making the request.');
};
xhr.send();
}
function createCORSRequest(method, url) {
var xhr = new XMLHttpRequest();
if ("withCredentials" in xhr) {
// XHR for Chrome/Firefox/Opera/Safari.
xhr.open(method, url, true);
} else if (typeof XDomainRequest != "undefined") {
// XDomainRequest for IE.
xhr = new XDomainRequest();
xhr.open(method, url);
} else {
// CORS not supported.
xhr = null;
}
return xhr;
}
ServerSide Code:
.htaccess file
<FilesMatch "\.('mp3')$">
ForceType application/octet-stream
Header set Content-Disposition attachment
</FilesMatch>
The problem is browser compatibility of Safari browser in effective usage of the Blobs. So I just removed the above snippet and used the basic anchor tag for my operations.
if(navigator.userAgent.indexOf("Safari") != -1){
var a = $("<a>").attr("href", url).attr("download", "MyFile.mp3").appendTo("body");
a[0].click();
a.remove();
}
I've the following js code to upload image to imgur using Auth.
<script type="text/javascript">
window.ondragover = function(e) {e.preventDefault()}
window.ondrop = function(e) {e.preventDefault(); upload(e.dataTransfer.files[0]); }
function upload(file) {
if (!file || !file.type.match(/image.*/)) return;
document.body.className = "uploading";
var fd = new FormData();
fd.append("image", file);
var xhr = new XMLHttpRequest();
xhr.open("POST", "https://api.imgur.com/3/image.json");
xhr.onload = function() {
var code = '[img]' + JSON.parse(xhr.responseText).data.link + '[/img]';
var editor = eval('opener.' + 'clickableEditor');
editor.performInsert(code);
javascript:window.close()
}
xhr.setRequestHeader('Authorization', '39-letter-client-secret-code');
xhr.send(fd);
}
</script>
It doesn't uploads image to the imgur, but it returns data "undefined". Can you please mention me if I'm missing something here?
I've seen an issue in this line;
xhr.setRequestHeader('Authorization', '39-letter-client-secret-code');
I've changed it to;
xhr.setRequestHeader('Authorization', 'Client-ID 15-letter-Client-ID');
and it works. Sorry to bother you.