Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel 8 file upload validation fails with any rule

I want to validate a file upload but with literally any validation rule, I get "The (name of input) failed to upload." I've seen this issue in a few places but none of the solutions worked for me.

I'm using Laravel 8.0, php 8.0.2, and nginx/1.18.0 on ubuntu.

Controller:

public function uploadMedia (Request $request)
{
    $request->validate([
        'file' => 'required',
        'alt' => 'required',
    ]);
    dd('valid');
}

Blade file:

@if($errors->any())
    @foreach ($errors->all() as $error)
        <p class="alert error">{{ $error }}</p>
    @endforeach
@endif

<form method="POST" action="/media" enctype="multipart/form-data">
    @csrf
    <input type="file" name="file" />
    <input type="text" name="alt" placeholder="Write a short description of the image under 160 characters." />
    <button type="submit">Upload</button>
</form>

If I get rid of the validation rule for 'file' it works, I get to the dd.

$request->validate([
    'file' => '', // works if I do this
    'alt' => 'required',
]);

I've seen other people have this issue and I've tried:

  • Putting another rule (max:10000, image) instead of 'required' for the file – still get the same error.
  • Changing the values php.ini to post_max_size = 201M and upload_max_filesize = 200M (this shouldn't be an issue in the first place because the image I am trying to upload is a 136kb jpg). Verified with phpinfo();
  • After changing these values, reloading nginx and php-fpm
  • Rebooting the VM
  • Checking that all the double and single quotes are the correct character
  • Trying to upload other filetypes like png or txt, same error.
  • Putting 'image' as the first validation rule which worked for someone here
  • Removing the extra comma at the end of the rules array
  • Changing the name of the file input to something other than 'file'
  • Using a different browser (Firefox and Chrome)
  • Disabling all my browser extensions
  • Writing the validation like this instead (still get the same error):
$validator = Validator::make($request->all(), [
    'file' => 'required',
    'alt' => 'required'
]); 
if ($validator->fails()) {
    return redirect('/media')->withErrors($validator);
}

If I dd($request) before validating:

Illuminate\Http\Request {#44 ▼
  #json: null
  #convertedFiles: null
  #userResolver: Closure($guard = null) {#255 ▶}
  #routeResolver: Closure() {#264 ▶}
  +attributes: Symfony\Component\HttpFoundation\ParameterBag {#46 ▶}
  +request: Symfony\Component\HttpFoundation\ParameterBag {#45 ▼
    #parameters: array:2 [▼
      "_token" => "RrjAA2YvnSd3EYqg8vAwoWT4y6VenJzGjb5S72SU"
      "alt" => "dsfghdf"
    ]
  }
  +query: Symfony\Component\HttpFoundation\InputBag {#52 ▶}
  +server: Symfony\Component\HttpFoundation\ServerBag {#49 ▶}
  +files: Symfony\Component\HttpFoundation\FileBag {#48 ▼
    #parameters: array:1 [▼
      "file" => Symfony\Component\HttpFoundation\File\UploadedFile {#33 ▼
        -test: false
        -originalName: "Screen Shot 2021-03-08 at 9.33.19 AM.png"
        -mimeType: "application/octet-stream"
        -error: 6
        path: ""
        filename: ""
        basename: ""
        pathname: ""
        extension: ""
        realPath: "/var/www/[my domain]/public"
        aTime: 1970-01-01 00:00:00
        mTime: 1970-01-01 00:00:00
        cTime: 1970-01-01 00:00:00
        inode: false
        size: false
        perms: 00
        owner: false
        group: false
        type: false
        writable: false
        readable: false
        executable: false
        file: false
        dir: false
        link: false
      }
    ]
  }
  +cookies: Symfony\Component\HttpFoundation\InputBag {#47 ▶}
  +headers: Symfony\Component\HttpFoundation\HeaderBag {#50 ▶}
  #content: null
  #languages: null
  #charsets: null
  #encodings: null
  #acceptableContentTypes: null
  #pathInfo: "/media"
  #requestUri: "/media"
  #baseUrl: ""
  #basePath: null
  #method: "POST"
  #format: null
  #session: Illuminate\Session\Store {#296 ▶}
  #locale: null
  #defaultLocale: "en"
  -preferredFormat: null
  -isHostValid: true
  -isForwardedValid: true
  -isSafeContentPreferred: null
  basePath: ""
  format: "html"
}
like image 323
camille Avatar asked Nov 06 '22 02:11

camille


1 Answers

Error value of 6 means UPLOAD_ERR_NO_TMP_DIR. Ensure that your system has a properly configured upload temp directory by running php -i from command line (or phpinfo(); from a web page) and checking for the upload_tmp_dir key. On a typical Linux system this will be something like /tmp. You can set the value in php.ini if needed. Ensure permissions are correct on the listed folder, such that the web server process is allowed to write to it.

Do not attempt to use one of your publicly-accessible folders as an upload directory (e.g. saving directly to storage/app/public or similar.) Your application code should move the file into storage as described in the documentation; something like this:

public function uploadMedia(Request $request)
{
    $request->validate([
        'file' => ['required', 'file', 'image'],
        'alt' => ['required', 'string'],
    ]);
    $path = $request->file->store('images');
    return redirect()->route('whatever')->with('success', "File saved to $path");
}
like image 112
miken32 Avatar answered Nov 14 '22 21:11

miken32