Reputation: 2210
I've spent a lot of time to solve my problem but without success.
I have an Angular 5 client and I want to send a file to my SpringBoot web service so that I can handle with that file on web service side.
My template:
<div class="dropdown-content">
<label (click)="openDialog()">Upload from xls</label>
<label>Save to xls</label>
<label>Link 3</label>
<input type="file" class="inputFile" style="display:none" (change)="handleFileInput($event.target.files)">
</div>
I'd like to have the possibility to choose a file after clicking on a label Upload from xls:
openDialog() {
let myInputFile = <HTMLElement>document.querySelector('.inputFile');
myInputFile.click();
}
//This method is called after choosing a file
handleFileInput(files: FileList) {
var file = this.fileToUpload = files.item(0);
this.uploadFileService.pushFileToStorage(file);
}
Next we call this.uploadFileService.pushFileToStorage(file);
@Injectable()
export class UploadFileService {
constructor(private http: Http, private globals: Globals, private httpClient: HttpClient) { }
pushFileToStorage(file) {
let headers = new Headers();
let options = new RequestOptions({ headers: headers }); // Create header
let formData = new FormData();
formData.append('file', file); // Append file to formdata
console.log(file);
const req = this.httpClient.post('http://localhost:' + this.globals.tomcatPort + '/utils/saveFromFile', JSON.stringify(formData));
req.subscribe((data) => {
console.log(data); // Sucess response
}, (err: HttpErrorResponse) => {
// Erro response
if (err.error instanceof Error) {
//client side error
console.log('An error occured: ', err.error.message);
}
else {
console.log('Backend returned code', err.status, 'body was ', err.error);
}
})
On the WebService side, my StorageController looks like (temporarily, for tests)
@RestController
@CrossOrigin(origins = "http://localhost:4200", maxAge = 3600)
@RequestMapping("/utils")
public class StorageController {
@PostMapping(value = "/saveFromFile", consumes = "multipart/form-data", produces = MediaType.APPLICATION_JSON_VALUE)
public void saveFromFile(@RequestParam("file") MultipartFile multipartFile) {
System.out.println(multipartFile);
}
@Bean
public CommonsMultipartResolver multipartResolver() {
CommonsMultipartResolver multipart = new CommonsMultipartResolver();
multipart.setMaxUploadSize(3 * 1024 * 1024);
return multipart;
}
@Bean
@Order(0)
public MultipartFilter multipartFilter() {
MultipartFilter multipartFilter = new MultipartFilter();
multipartFilter.setMultipartResolverBeanName("multipartResolver");
return multipartFilter;
}
}
Currently I get the error:
Failed to load http://localhost:8180/utils/saveFromFile: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4200' is therefore not allowed access. The response had HTTP status code 403.
I have problem with CORS only when I'm trying to send a file.
Thank you in advance! Mateusz
Upvotes: 0
Views: 442
Reputation: 2210
Ok, finally I solved my problem in very easy way:
Angular template:
<div class="dropdown-content">
<label (click)="openDialog()">Upload from xls</label>
<label>Save to xls</label>
<label>Link 3</label>
<input type="file" class="inputFile" style="display:none" (change)="handleFileInput($event)">
</div>
Angular component:
openDialog() {
let myInputFile = <HTMLElement>document.querySelector('.inputFile');
myInputFile.click();
}
//This method is called after choosing a file
handleFileInput(event) {
var file = this.fileToUpload = <File>event.target.files[0];
this.uploadFileService.pushFileToStorage(file);
}
Angular Service:
pushFileToStorage(file) {
const fd = new FormData();
fd.append('file', file, file.name);
this.httpClient.post('http://localhost:' + this.globals.tomcatPort + '/utils/saveFromFile', fd)
.subscribe(res => {
this.dataStorageService.getDictionaryItems();
})
}
and in WebService in my Controller:
@PostMapping(value = "/saveFromFile", consumes = "multipart/form-data", produces = MediaType.APPLICATION_JSON_VALUE)
public void saveFromFile(@RequestParam("file") MultipartFile file) throws IOException {
File convFile = new File(file.getOriginalFilename());
convFile.createNewFile();
FileOutputStream fos = new FileOutputStream(convFile);
fos.write(file.getBytes());
fos.close();
storageService.saveWordsFromFile(convFile);
}
And that's all. It works!
Upvotes: 0
Reputation: 1751
In UploadFileService
you need to import
import {HttpClient, HttpHeaders} from '@angular/common/http'
And while calling POST service you can do like if you want to set Authorization
header with some token then this is the way to set header in general. And again if you want to add more then simply append them
const req = this.httpClient.post('http://localhost:' +
this.globals.tomcatPort + '/utils/saveFromFile', JSON.stringify(formData),
{headers: new HttpHeaders().set('Authorization', 'Basic jfghghjbhjb')});
If you don't want to use inline headers then you can create it's separate object like below
const headers = new HttpHeaders().set('Authorization', 'Basic jfghghjbhjb')
and you can use this
const req = this.httpClient.post('http://localhost:' +
this.globals.tomcatPort + '/utils/saveFromFile', JSON.stringify(formData),
{headers: headers});
Upvotes: 1