Karan Saxena
Karan Saxena

Reputation: 59

File Upload in Angular giving error when posting POST request

I have an HTML form like this to upload files from front-end to back-end and do some operations:

<button mat-raised-button color="primary" type="button" style='margin-right:20px' (click)="selectFile()">Select File To Upload</button> 
<input #fileUploadInput type="file" id="fileUpload" hidden name="avatar" (change)="fileChangeEvent($event)">
<button mat-raised-button color="primary" type="button" style='margin-right:20px' enctype="multipart/form-data" (click)="uploadFile()">Submit</button>
        
<br><br>
<a class="generate-full-width" style="color: darkred;" *ngIf="fileName"><strong>{{fileName}}</strong></a>

The component.ts is:

export class uploadFileDialog {

  constructor(
    public dialogRef: MatDialogRef<AddProductDialog>,
    private uploadService: UploadService,
    private builder: FormBuilder, public dialog: MatDialog,
    @Inject(MAT_DIALOG_DATA) public data) {
  }

  @ViewChild('fileUploadInput', {static: false})
  fileUploadVariable: ElementRef;
  fileName;
  currentFile: File;
  filesToUpload = [];

  resetFile(){
    this.fileUploadVariable.nativeElement.value = "";
  }

  
  selectFile(){
    this.resetFile();
    let el: HTMLElement = this.fileUploadVariable.nativeElement as HTMLElement;
    el.click();
  }

  fileChangeEvent(fileInput: any) {
    let file = fileInput.target.files[0]
    console.log(file)
    //console.log(file.data.toString());
    this.filesToUpload = [];
    this.filesToUpload.push(file);
    this.fileName = file['name'];
  }

  uploadFile(){
    this.currentFile = this.fileName;
    console.log(this.currentFile);
    this.uploadService.uploadFile(this.currentFile)
      .subscribe((data) => {
        
        console.log(data)
      },
      error => {
        console.log(error)
      });
  }
}

Service.ts is:

uploadFile(file: File): Observable<any> {

    let headers = new HttpHeaders({
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, OPTIONS',
      //'Access-Control-Allow-Headers': 'X-Requested-With, content-type, Authorization'
      'Access-Control-Allow-Headers': 'Content-Type,Accept,X-Access-Token,X-Key,Authorization,X-Requested-With,Origin,Access-Control-Allow-Origin,Access-Control-Allow-Credentials,content-type=multipart/*'
    })

    let options = {headers:headers, observer: 'response'};

    const formData: FormData = new FormData();

    formData.append('file', file);

    //return this.http.post(this.url+'/fileUpload/upload', formData,options)
    const req = new HttpRequest('POST', this.url+'/fileUpload/upload', formData, {
      reportProgress: true,
      responseType: 'json'
    });

    return this.http.request(req);
  }

The controller file at Java backend is:

@RestController
@CrossOrigin(origins = "*", allowedHeaders="*", exposedHeaders="Access-Control-Allow-Origin")
@RequestMapping("/fileUpload")

public class FileController {
    
    private final FileService fileService;
     
    @Autowired
    public FileController(FileService fileService) {
        this.fileService = fileService;
    }
 
    @PostMapping(value = "/upload")
    public void handleFileUpload(@RequestParam("file") MultipartFile file) throws IOException {
        fileService.storeFile(file);
    }}

and the Service File at Java Backend is:

@Service
public class FileService {

    private static final String FILE_DIRECTORY = "D:\\temp";
     
    public void storeFile(MultipartFile file) throws IOException {
        Path filePath = Paths.get(FILE_DIRECTORY + "\" + file.getOriginalFilename());
 
        Files.copy(file.getInputStream(), filePath, StandardCopyOption.REPLACE_EXISTING);
    }
    
}

I am able to see the file name when uploading in the console. Also, in the body of the request, the formData is showing the xml file as content in the Networks tab. I Java console, I am getting the error:

2020-12-15 12:26:53.144  WARN 9688 --- [nio-8080-exec-8] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.multipart.support.MissingServletRequestPartException: Required request part 'file' is not present]

Error in front-end console:

HttpHeaderResponse {headers: HttpHeaders, status: 400, statusText: "OK", url: "http://localhost:8080/fileUpload/upload", ok: false, …}
headers: HttpHeaders {normalizedNames: Map(0), lazyUpdate: null, lazyInit: ƒ}
ok: false
status: 400
statusText: "OK"
type: 2
url: "http://localhost:8080/fileUpload/upload"
__proto__: HttpResponseBase

What am I doing wrong?

Upvotes: 0

Views: 1872

Answers (1)

Ganesh
Ganesh

Reputation: 6016

You are sending only file name but not actual file blob.

Try to do below changes,

component.ts :

  uploadFile() {
    this.currentFile = this.fileName;
    console.log(this.currentFile, this.filesToUpload[0]);
    this.uploadService.uploadFile(this.currentFile, this.filesToUpload[0])
      .subscribe((data) => {
        console.log(data)
      },
      error => {
        console.log(error)
   });
  }

service.ts

uploadFile(fileName: string, file: File): Observable<any> {

   let headers = new HttpHeaders({
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, OPTIONS',
      'Access-Control-Allow-Headers': 'Content-Type,Accept,X-Access-Token,X-Key,Authorization,X-Requested-With,Origin,Access-Control-Allow-Origin,Access-Control-Allow-Credentials,content-type=multipart/*'
   })

  let options = {headers:headers, observer: 'response'};

  const formData: FormData = new FormData();

  formData.append('fileName', fileName);
  formData.append('file', file);

  const req = new HttpRequest('POST', this.url+'/fileUpload/upload', formData, {
    reportProgress: true,
    responseType: 'json'
  });

 return this.http.request(req);
}

Please refer this link to know more about formData

Upvotes: 2

Related Questions