How can i implement download file From API - java

I can't download file from my friend service java code from angular that i implement and i don't know how to implement download file from angular please help me
My Code Angular
private _download$ = new Subject<void>();
**this._download$.pipe(switchMap(()=>this._downloadFile())).subscribe(resultBlob =>{
console.log("Success to Next ")
this.loadFile(resultBlob)
},(exception:any)=>{
console.log("exception: ",exception)
},()=>{
console.log("Complete: ")
})
}**
**private _downloadFile(){
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/octet-stream',
responseType : 'blob',
Accept : 'application/octet-stream',
observe : 'response'
})
};**
return this.http.get<Blob>('/col-corecollection-service/exclusion/download-file/'+this.exclusionCode,httpOptions)
}
private download(){
this._download$.next();
}
loadFile(data: any) {
var blob = new Blob([data], {type: 'application/octet-stream'});
var downloadURL = window.URL.createObjectURL(data);
window.open(downloadURL);
}**
And I have code service that my friend implement like this
#GetMapping("/exclusion/download-file/{exclCode}")
#ResponseStatus(HttpStatus.OK)
public ResponseEntity<Resource> exclusionDownloadFile(
#Size(min = 1, max = 50)
#PathVariable String exclCode
) {
if (!this.exclusionService.existsExclusionById(exclCode)) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Exclusion code " + exclCode + " not found.", null);
}
SearchExclFilenameExclBlobByIdResponse downloadFile = this.exclusionService.searchExclFilenameExclBlob(exclCode);
byte[] fileData = downloadFile.getExclBlob();
Resource resource = new InputStreamResource(new ByteArrayInputStream(fileData));
return ResponseEntity.ok()
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + downloadFile.getExclFilename() + "\"")
.body(resource);
}
when i click my download button and then it can't downloadFile to me please help

Try passing responseType outside headers
Remove responseType from header:
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/octet-stream',
Accept : 'application/octet-stream',
observe : 'response'
})
};
Here is updated code for passing responseType outside headers:
return this.http.get<Blob>('/col-corecollection-service/exclusion/download-file/'+this.exclusionCode,{headers: httpOptions.headers, responseType: 'blob'})
Then if you want download use fileSaver:
var file = new Blob([data], { type: "application/octet-stream" });
this.fileSaverService.save(file);

I use ngx-filesaver which provides the fileSaver directive.
<button class="mdi mdi-download btn btn-primary"
fileSaver
[fileName]="'yourfile.xxx'"
[url]="'/col-corecollection-service/exclusion/download-file/' + this.exclusionCode"
(change)="upload($event)">
Download
</button>

Related

How to receive file csv from java with angular

I have a rest api which returns a file.csv
and then I check that the response is 200, and datas are also in responsed.body.
But the brower didn't download the csv file.
Here is the API :
ResponseEntity<Resource> exportCsv() throws IOException {
/*
*
*/
InputStreamResource resource = new InputStreamResource(new FileInputStream(file));
HttpHeaders headers = new HttpHeaders();
headers.add("Content-disposition", "attachment; filename=sample.csv");
headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
headers.add("Pragma", "no-cache");
headers.add("Expires", "0");
return ResponseEntity.ok()
.headers(headers)
.contentLength(file.length())
.contentType(MediaType.parseMediaType("text/csv"))
.body(resource);
}
Here is the Angular
this.stickService.exportCsv( this.stickSearch ).subscribe(
response => this.downloadFile(response),
err => console.log('Error downloading the file.' + err.message
));
downloadFile(data: Response) {
const blob = new Blob([data], { type: 'text/csv' });
const url = window.URL.createObjectURL(blob);
window.open(url);
}
exportCsv( stickSearch: StickSearch ): Observable<any> {
const headers = this.oAuthService.putTokenInHeaders(this.headers);
let params = new HttpParams({encoder: new HttpURIEncoder()});
if (stickSearch.searchString() !== '') {
params = params
.append('search', stickSearch.searchString())
}
return this.httpClient.get(this.exportCsvUrl + '/exportCsv',
{
responseType: 'text',
params: params,
headers
});
}
I got correct data at response body.
But the download failed. 'Error downloading the file.Http failure during parsing for myURL '
Thanks for helping
It work now, this is consequence
Thanks a lot !
I can see that you are taking the output provided by the server and then building an URL off that CSV. That won't be necessary.
If you just want to download the CSV, then all you are missing is the following in your Java code:
headers.add("Content-disposition", "attachment; filename=sample.csv");
Once you have the header in place, you can get rid of the downloadFile method and probably change the this.httpClient.get request into a window.open.
See if this solves your problem and provide feedback in either case.
By default HttpClient expects that data from server will come in json format. Angular tries to parse text body as json. And that leads to exсeption. In the stickService when you do request the data, you have to specify type or result as text:
constructor (private httpClient: HttpClient){
}
public exportCsv(stickSearch: any) {
return httpClient.get('http://someurl', {responseType: 'text'});
}
Another one point that you use window.open(url). Most browsers block popup windows by default. So maybe it would be better to use an anchor element.
downloadFile(data: Response) {
const blob = new Blob([data], { type: 'text/csv' });
const url = window.URL.createObjectURL(blob);
const anchor = document.createElement('a');
anchor.download = 'myfile.txt'; // here you can specify file name
anchor.href = url;
document.body.appendChild(anchor);
anchor.click();
document.body.removeChild(anchor);
}
Here is the I'm using for this feature.
First, use 'Accept' headers.
Second, set responseType to 'text', the default is 'json'.
Third, the download code.
getCsv(): Observable<any> {
let headers = new HttpHeaders();
headers = headers.set('Accept', 'application/csv');
return this.http.get('SOME__URL', {
headers: headers,
responseType: 'text'
});
}
exportReportCSV() {
getCsv().subscribe( response => {
const link = document.createElement('a');
link.href = window.URL.createObjectURL(new Blob([response], {type: 'text/csv'}));
link.download = this.report.name + '.csv';
link.click();
});

OAuth token Unauthorized on browser

I'm using Angular 7 and I got a problem with Headers.
This is my code:
signin() {
let signinData = this.signinForm.value;
this.encoded = btoa("my-trusted-client:secret");
let header = new Headers();
header.append('Authorization', 'Basic ' + this.encoded);
header.append('Content-type', 'application/x-www-form-urlencoded; charset=utf-8');
this.http.post(this.url + '/oauth/token?grant_type=password&username=' + signinData.username + '&password=' + signinData.password, { headers: header })
.subscribe(data => {
console.log(data);
})
}
Output Error:
error: "Unauthorized"
message: "Unauthorized"
path: "/barometre/oauth/token"
status: 401
timestamp: "2019-04-19T12:35:47.699+0000"
When I test it on Postman I got the results:
Edit:
The problem was on the request signature. I changed this:
this.http.post(this.url + '/oauth/token?grant_type=password&username=' + signinData.username + '&password=' + signinData.password, { headers: header })
By This:
this.http.post(this.url + '/oauth/token', params, { headers: header })
with
let params: URLSearchParams = this.serialize(this.data);
and generate new function
serialize(obj: any): URLSearchParams {
let params: URLSearchParams = new URLSearchParams();
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
var element = obj[key];
params.set(key, element);
}
}
return params;
console.log(params);
};
You need to pass HttpHeaders in post. Check here
const header= {
headers: new HttpHeaders({
'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8',
'Authorization': 'Basic ' + this.encoded
})
};
Also make sure that your Authorization token is valid.
The problem was on the request signature. I changed this:
this.http.post(this.url + '/oauth/token?grant_type=password&username=' + signinData.username + '&password=' + signinData.password, { headers: header })
By This:
this.http.post(this.url + '/oauth/token', params, { headers: header })
with
let params: URLSearchParams = this.serialize(this.data);
and generate new function
serialize(obj: any): URLSearchParams {
let params: URLSearchParams = new URLSearchParams();
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
var element = obj[key];
params.set(key, element);
}
}
return params;
console.log(params);
};

Download a file using Angular 6 and Spring Rest API

I have a problem downloading a file from a rest api using angular 6
Back-end method
#RequestMapping(value = "/print/{id}")
public ResponseEntity<byte[]> generateReport(#PathVariable("id") long id_project){
Map<String, Object> mapper = new HashMap<String, Object>();
byte[] content = exportService.export(mapper, ReportUtils.testReport, ReportUtils.FileFormat.PDF.toString());
return new ResponseEntity<>(content, Utils.getPDFHeaders("Situation_test.pdf"), HttpStatus.OK);
}
Mathod getHeader
public static HttpHeaders getPDFHeaders(String fileName) {
HttpHeaders head = new HttpHeaders();
head.setContentType(MediaType.parseMediaType("application/pdf"));
head.add("content-disposition", "attachment; filename=" + fileName);
head.setContentDispositionFormData(fileName, fileName);
head.setCacheControl("must-revalidate, post-check=0, pre-check=0");
return head;
}
My Angular Service
download(url: string): any {
let headers = new HttpHeaders();
headers = headers.append('Authorization', 'Bearer ' + this.getToken());
this.http.get(this.API_URL + url, {headers: headers}).subscribe((res) => {
const file = new Blob([res], {
type: 'application/pdf',
});
const a = document.createElement('a');
a.href = this.API_URL + (<any>res)._body;
a.target = '_blank';
document.body.appendChild(a);
a.click();
return res;
}, error => {
let alert: any = {
title: 'Notify Title',
body: 'Notify Body',
};
alert.body = error.error.message || JSON.stringify(error.error);
alert.title = error.error.error;
alert = this.alertService.handleError(error);
alert.position = 'rightTop';
console.log(error);
this.alertService.notifyError(alert);
return error;
});
}
I have already tried my API using PostMan and it word perfectly but in Angular it give me this error
HttpErrorResponse {headers: HttpHeaders, status: 200, statusText: "OK", url: "http://localhost:8080/api/projects/print/1", ok: false, …}
error: {error: SyntaxError: Unexpected token % in JSON at position 0 at JSON.parse (<anonymous>) at XMLHttp…, text: "%PDF-1.4↵%����↵3 0 obj↵<</Filter/FlateDecode/Lengt…25f1>]/Root 8 0 R/Size 10>>↵startxref↵1049↵%%EOF↵"}
headers: HttpHeaders {normalizedNames: Map(0), lazyUpdate: null, lazyInit: ƒ}
message: "Http failure during parsing for http://localhost:8080/api/projects/print/1"
name: "HttpErrorResponse"
ok: false
status: 200
statusText: "OK"
url: "http://localhost:8080/api/projects/print/1"
Try adding content-type to your request headers.
You can try this as an exemple:
let headers = new Headers({'Content-Type': 'application/pdf', 'Accept': 'application/pdf'});

File size is zero when passing multiple files to the Spring Controller

I am trying to post a file (single file or multiple files) along with some JSON data using AngularJS and Spring MVC.
I tried as shown below:
JS:
(function () {
'use strict';
var myApp = angular.module('app');
myApp.controller('filesWithJSONController', function ($scope, fileUploadService) {
$scope.uploadFile = function () {
var file = $scope.myFile;
var uploadUrl = myApplnURL + '/showInfo/getInformationTest';", //Url of web service
var fd=new FormData();
angular.forEach($scope.files,function(file){
fd.append('file',file);
});
fd.append('properties', new Blob([JSON.stringify({
"name": "root",
"password": "root"
})], {
type: "application/json"
}));
promise = fileWithJSONService.sendInformation(fd,uploadUrl);
promise.then(function (response) {
$scope.serverResponse = response;
}, function () {
$scope.serverResponse = 'An error has occurred';
})
};
});
})();
(function () {
'use strict';
var myApp = angular.module('app');
myApp.service('fileWithJSONService', function ($http, $q) {
this.sendInformation = function (fd, uploadUrl) {
var deffered = $q.defer();
var config = {
headers : {
'Content-Type': undefined
}
}
$http.post(uploadUrl, fd, config).then(function (response) {
console.log("response " + response);
}, function (errResponse) {
console.error('Error in request' + errResponse);
deferred.reject(errResponse);
});
...
Spring Controller:
#Controller
#RequestMapping("/showInfo")
public class InfoController{
#RequestMapping(value = "/getInformationTest", method = RequestMethod.POST, consumes = {"multipart/form-data"})
#ResponseBody
public String sendInformationTest(#RequestPart("properties") ConnectionProperties properties, #RequestPart("file") List<MultipartFile> multiPartFileList){
System.out.println("In spring controller");
//business logic
}
With the above code, it is showing the multiPartFileList size as zero in Spring Controller.
But if I change the code to take only one file instead of multiple files, it is showing the file information successfully. Any input?
try with:
var fd = new FormData();
fd.append('file', file);//replace with forEach
$http.post(uploadUrl, fd, {
transformRequest: angular.identity,//overrides Angular's default serialization, leaving our data intact.
headers: {'Content-Type': undefined}//lets the browser detect the correct Content-Type as multipart/form-data, and fill in the correct boundary.
})
.success(function(){})
.error(function(){});
Backend - Spring:
#RequestMapping(value ="/upload", method = RequestMethod.POST)
public ResponseEntity handleFileUpload(#RequestParam("file") MultipartFile[] files){
//add the others params & logic
}

Cannot upload file using Angular and Spring Boot

I'm trying to upload a file with AngularJS and Spring Boot controller. I have 2 problems:
1) When I use an HTML form 'submit' I get exceeded size even though I have set the max size of file to 128M. The code looks like this:
public class AppConfig {
#Bean
public MultipartConfigElement multipartConfigElement() {
factory.setMaxFileSize("128MB");
factory.setMaxRequestSize("128MB");
return factory.createMultipartConfig();
}
}
It seems that Spring ignores these settings.
2) When I'm trying to upload a file, I get the error:
org.springframework.web.multipart.MultipartException: The current request is not a multipart request
The Angular controller looks like this:
$scope.uploadFile=function(){
var formData=new FormData();
formData.append("file",file.files[0]);
$http.post('/content-files/upload /', file.files[0], {
transformRequest: function(data, headersGetterFunction) {
return data; // do nothing! FormData is very good!
},
headers: {'Content-Type': undefined }
})
.success(function(){
console.log('Post Succeded !');
})
.error(function(){
console.log('Post Failed .');
});
}
and the Spring controller looks like this:
#RequestMapping(value = "/content-files/upload/", method = RequestMethod.POST )
public #ResponseBody String handleFileUpload( #RequestParam("file") MultipartFile file) {
System.out.println("BrandController.uploadMultipart()");
String name=file.getName();
if (!file.isEmpty()) {
try {
byte[] bytes = file.getBytes();
BufferedOutputStream stream =
new BufferedOutputStream(new FileOutputStream(new File(name)));
stream.write(bytes);
stream.close();
return "You successfully uploaded " + name + "!";
} catch (Exception e) {
return "You failed to upload " + name + " => " + e.getMessage();
}
} else {
return "You failed to upload " + name + " because the file was empty.";
}
}
I tried changing the JS controller to:
$http.post('/content-files/upload /', file.files[0], {
headers: { 'Content-Type': undefined },
transformRequest: angular.identity
})
but I get the same error as above. When I try changing the JS controller to:
headers: { 'Content-Type': 'multipart/form-data' },
transformRequest: angular.identity
I get the error the request was rejected because no multipart boundary was found.
It seems that I have tried all combinations with the parameters, and still nothing worked. What do I need to do to get this file upload to work?
Try with this:
var formData = new FormData();
formData.append('file',file.files[0]);
$http.post('/content-files/upload /', formData, {
headers: { 'Content-Type': undefined },
transformRequest: angular.identity
})
Based on the MultipartAutoConfiguration code, the way to increase the size limit on uploads (by default max is 1 MB) with Spring Boot is the following properties:
multipart.maxFileSize=129Mb
multipart.maxRequestSize=129Mb
Regarding jquery multipart uploads, the way you are doing it does not appear correct, there are other good references that you can check for, I have seen plenty within Stackoverflow itself.

Categories

Resources