Encountering an issue when trying to upload a photo from Angular 8 to Laravel: receiving a "Call to a member function extension() on null" error

In my project using Angular 8 for the front end and Laravel 5.8 for the backend, I encountered an issue with uploading photos. I found guidance in this tutorial from ACADE MIND.

Here is my template code :

 <input  *ngIf="photoEdit" enctype="multipart/form-data" type="file" (change)="onFileChanged($event)" #fileInput>
 <button *ngIf="photoEdit" class="btn btn-xs btn-danger" (click)="onUpload()"> Save</button>
 <button class="btn btn-small btn-primary" (click)="editPhoto()">Change Photo</button>

Within the following method :

public onFileChanged(event) {
    this.selectedFile = event.target.files[0];
    console.log(this.selectedFile);
  }

The file selection is successfully logged in the console.

The onUpload() method :

onUpload() {
    const uploadData = new FormData();
    uploadData.append('photo', this.selectedFile,this.selectedFile.name);
   
    this.http.post('http://127.0.0.1:8000/api/photo/upload', uploadData, this.authService.getHeader())
      .subscribe(event => {
        console.log(event);
      });
  }

getHeader()

public getHeader() {
    var token: string;
    token = "bearer" + this.getToken();
    let headers = new HttpHeaders({
      'Content-Type': 'application/json',
      'Authorization': token
    });
    let options = { headers: headers };
    return options;
  }

I am encountering the following error message:

   error : "Call to a member function extension() on null"

When uploading a photo using Postman, everything works fine. The server logs show:

[Tue Nov 26 07:34:27 2019] Log In
[Tue Nov 26 07:34:34 2019] POST /api/photo/upload HTTP/1.1
...

Server Side function:

    public function upload(request $request)
        {
            error_log($request);
            $extension = $request->file('photo')->extension();

            if ($request->hasFile('photo')) {
                error_log("FILE");
            }
            $fileName = "logedUserName";
            $fileName =  $fileName . "." . $extension;
            $savedPhotoName = $request->photo->storeAs('public', $fileName);
            return $savedPhotoName;
        }

Answer №1

Consider updating your Laravel function to handle empty uploads by returning an error message. Here's an example:

public function upload(request $request)
{
    // Check if a file was provided
    if ($request->hasFile("photo")) {
        error_log("Error::: No file provided in upload");
        return "error_no_file";
    }
    else
    {
        // Validate the file (size, type, etc.)

        $file = $request->file("photo");
        $filename = "loggedUserName-" . "." . $file->getClientOriginalExtension();

        // Save file to storage/app/photos directory
        $path = $file->storeAs("photos", $filename);

        // Return path of the uploaded file
        return $path;
    }
}

Additionally, try adjusting the 'Content-Type' header in your getHeader() method to 'multipart/form-data' or removing it altogether instead of using 'application/json' as a workaround.

Answer №2

I have discovered the root cause, which is a mismatch in the "Content-Type". To illustrate, I have shared two server logs.

1. Log with Issue


[Tue Nov 26 07:34:27 2019] Log In
[Tue Nov 26 07:34:34 2019] POST /api/photo/upload HTTP/1.1
Accept:          application/json, text/plain,
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,bn;q=0.8
Authorization:`   `bearereyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3Mi...
Connection:      keep-alive
Content-Length:  39015
Content-Type:    application/json
Host:            127.0.0.1:8000
Origin:          http://localhost:4200
Referer:         http://localhost:4200/profile
Sec-Fetch-Mode:  cors
Sec-Fetch-Site:  cross-site
User-Agent:      Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537...

------WebKitFormBoundaryvkYLBOFceCLCopiW
    Content-Disposition: form-data; name="photo"; filename="3_4_5.png"
    Content-Type: image/png

The log analysis reveals a type mismatch in "Content-Type:". The specified content type is:

Content-Type:    application/json

The issue stemmed from providing the content type as "application/json" while sending the JWT Token as a header. After correcting the content type, the process started working. A new method was implemented without specifying a content type.


public getHeaderFile() {
    var token: string;
    token = "bearer" + this.getToken();
    let headers = new HttpHeaders({
      'Authorization': token
    });
    let options = { headers: headers };
    return options;
}

2. Functional Log


[Tue Nov 26 11:09:19 2019] Log In
[Tue Nov 26 11:09:35 2019] POST /api/photo/upload HTTP/1.1
Accept:          application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,bn;q=0.8
Authorization:   bearereyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3Mi...
Connection:      keep-alive
Content-Length:  2051
Content-Type:    multipart/form-data; boundary=----WebKitFormBoundaryzfjTeLXzaEUrfSO1
Host:            127.0.0.1:8000
Origin:          http://localhost:4200
Referer:         http://localhost:4200/profile
Sec-Fetch-Mode:  cors
Sec-Fetch-Site:  cross-site
User-Agent:      Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537...

[Tue Nov 26 11:09:36 2019] E:\ProgramsFiles\xampp\tmp\phpB2DE.tmp
[Tue Nov 26 11:09:36 2019] FILE RECEIVED!

In this log, the content type is:

Content-Type:    multipart/form-data; boundary=----WebKitFormBoundaryzfjTeLXzaEUrfSO1

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the proper way to manage errors caught in the ngrx effect's catch block and store them in the component?

I am seeking advice on how to manage the scenario when data loading fails in my component. I would like to know if it is preferable to include selectors for error handling or address it within effects. My experience with ngrx and fetching data through ac ...

The TypeScript error message indicates that a value typed as 'string | undefined' cannot be assigned to a type 'string'

In my TypeScript-based React application where I am utilizing material-ui for components, I am currently working on creating a wrapper for material-ui's input. Here is the code snippet: import FormControl, { FormControlProps } from "@material-ui/core ...

The URL "http://localhost:8100" has been restricted by the CORS policy, as it lacks the necessary 'Access-Control-Allow-Origin' header on the requested resource

`The CORS policy has blocked access to the XMLHttpRequest at 'http://localhost/phpfile/leave-option.php' from the origin 'http://localhost:8100'. This is due to the absence of the 'Access-Control-Allow-Origin' header on the re ...

Angular 2: Change Boolean value depending on a condition

I find myself facing a challenge with a search-bar feature. My goal is to display all the filtered names when the input value reaches a length of 2 or more characters. After successfully extracting the value.length from the input field, I encountered a ro ...

Laravel 5 is reporting that it cannot locate the class 'AppHttpControllersArtisan'

Currently, I am diving into the world of Laravel and learning through hands-on coding. I successfully created migrations and seeds which work smoothly when executed in the terminal. But recently, I attempted to integrate this code snippet into my HomeContr ...

Guide to organizing elements in an array within a separate array

Our array consists of various items: const array = [object1, object2, ...] The structure of each item is defined as follows: type Item = { id: number; title: string contact: { id: number; name: string; }; project: { id: number; n ...

Error encountered while injecting Angular dependencies in component constructor

Here is my newly created component. I am looking to allow users to adjust the count variable. import { Component, Inject } from '@angular/core'; @Component({ selector: 'app-likebtn', templateUrl: './likebtn.component.html&apos ...

Is it possible to pass a different variable during the mouse down event when using Konva for 2D drawing?

I am trying to pass an additional value in a mouse event because my handleMouseDown function is located in another file. stage.on('mousedown', handleMouseDown(evt, stage)) Unfortunately, I encountered an error: - Argument of type 'void&apos ...

Is it possible to visually distinguish the selected mat-grid-tile? Particularly when they are being created dynamically

On the user interface, I have a dynamic display of mat-grid-tile within a mat-grid-list. These tiles change in number and data based on backend values. When a user clicks on a mat-grid-tile, it triggers a function that receives the tile's data. My goa ...

Tips for aligning content produced by *ngFor within a bootstrap grid

I am trying to center content in a row using the Bootstrap grid system. While I have checked out various examples, such as this one, my case is unique because I am utilizing a separate angular component for generating the content. Here is the code snippet ...

Utilize a custom Angular2 validator to gain entry to a specific service

For accessing my custom http service from within a static method, consider the following example: import {Control} from 'angular2/common'; import {HttpService} from './http.service'; class UsernameValidator { static usernameExist( ...

Unable to locate module '@angular/core' while utilizing PrimeNG

After installing PrimeNg, I attempted to use the sidebar component in my project. However, upon running the project, an error occurred: ERROR in /home/haddad/projects/node_modules/primeng/components/sidebar/sidebar.d.ts (1,97): Cannot find module '@a ...

What is the reason behind the ability to reassign an incompatible function to another in TypeScript?

I discovered this question while using the following guide: https://basarat.gitbooks.io/typescript/content/docs/types/type-compatibility.html#types-of-arguments. Here is an example snippet of code: /** Type Heirarchy */ interface Point2D { x: number; y: ...

After updating to Angular 7, an error was encountered: "TypeError: Unable to execute map function on ctorParameters"

After updating my Angular project to version 7, I encountered a new issue. When running "ng serve --open" from the CLI, I received the following error message: Uncaught TypeError: ctorParameters.map is not a function at ReflectionCapabilities._own ...

Learn a simple method for converting or assigning an Observable to a Behavior Subject, allowing for seamless sharing between components

As a newcomer to Observable style programming, I have encountered a challenge regarding sharing user information across various components in my Angular app. My approach involves using BehaviorSubject to share this data, drawing inspiration from the concep ...

Generate a collection of elements using a different collection as a reference

I am struggling with an array of objects: let data = [{ createdDate: "2222", email: "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="087c6d7b7c3d487c6d7b7c266b6765">[email protected]</a>", histories: [ ...

The production build failed following the upgrade to ag-grid version 22.1.1

Since version 18, I have been utilizing ag-grid, and I am currently on version 20.0.0. I am now in the process of upgrading to the latest version - 22.1.1. After addressing warnings/errors caused by breaking changes, everything seems to be working fine, ...

Enhancing Readability of Public Static Member Variables in Typescript

In my node application, I am utilizing typescript and winston for logging purposes. One key element of my setup is the "Logger" class which consists of a "logger" member and an "init()" function. By exporting this class, I understand that the "logger" memb ...

AgGrid:CellRenderer and Observables

Having trouble getting my backend data to display in the AGGrid cell renderer component despite using observables Here are the methods I've attempted so far: Directly calling the service within the cellRenderer component Invoking the service in the ...

Why is it that the changes I make in the parent component do not reflect in my Angular component?

As I embarked on creating a custom select component, I began with the input below: @Input() options: SelectOption<UserRole>[] = []; The parent component (user editor) utilizes this select component and provides the options as shown below: roleOption ...