Fake a file upload with defined mimetype

Published 2 months ago by Zini

Hi,

I want to fake the upload of multiple types. It works for images, but I have a hard time finding out how to simulate other types of files.

Any not-image file gets inode/x-empty for mimetype, where I would like to see application/pdf.

// Mimetype ok
$file = \Illuminate\Http\UploadedFile::fake()->image('test.jpg');

// Mimetype issue: inode/x-empty
$file = \Illuminate\Http\UploadedFile::fake()->create('test.pdf');

// also tried this
$file->mimeType = 'application/pdf';

I did not find yet any solution in the Illuminate doc, or the Symfony doc.

lostdreamer_nl

strange, i've gone through the code just now, and it goes through:

  • Illuminate\Http\UploadedFile
  • Illuminate\Http\Testing\FileFactory
  • Illuminate\Http\Testing\File
    public static function from($filename)
    {
        $extension = pathinfo($filename, PATHINFO_EXTENSION);
        return self::getMimeTypeFromExtension($extension);
    }

    protected static function getMimeTypeFromExtension($extension)
    {
        return self::$mimes[$extension] ?? 'application/octet-stream';
    }

It should be getting the mimetype from the name you give, and pdf is in the list of extensions.

        'pdf' => 'application/pdf',

Testing it myself:


$file = \Illuminate\Http\UploadedFile::fake()->create('test.pdf');
dd($file);

File {#403 ▼
  +name: "test.pdf"
  +tempFile: stream resource @13 ▶}
  +sizeToReport: 0
  -test: true
  -originalName: "test.pdf"
  -mimeType: "application/pdf"
  -error: 0
  #hashName: null
  path: "/tmp"
  filename: "phpREZVKB"
  basename: "phpREZVKB"
  pathname: "/tmp/phpREZVKB"
  extension: ""
  realPath: "/tmp/phpREZVKB"
  aTime: 2018-07-11 20:50:45
  mTime: 2018-07-11 20:50:45
  cTime: 2018-07-11 20:50:45
  inode: 3407925
  size: 0
  perms: 0100600
  owner: 33
  group: 33
  type: "file"
  writable: true
  readable: true
  executable: false
  file: true
  dir: false
  link: false
}

What version of laravel are you on?

Zini

Thank you lostdreamer_nl, you are correct, it actually works to that point. I don't know how I missed that, I was looking in the wrong place.

Actually my problem happens after the upload, when I control the input file in a custom rule.

The uploaded file seems ok:

\Log::debug(print_r($file, true));

testing.DEBUG: Illuminate\Http\Testing\File Object
(
    [name] => esse.pdf
    [tempFile] => Resource id #645
    [sizeToReport] => 0
    [test:Symfony\Component\HttpFoundation\File\UploadedFile:private] => 1
    [originalName:Symfony\Component\HttpFoundation\File\UploadedFile:private] => esse.pdf
    [mimeType:Symfony\Component\HttpFoundation\File\UploadedFile:private] => application/pdf
    [error:Symfony\Component\HttpFoundation\File\UploadedFile:private] => 0
    [hashName:protected] => 
    [mimeType] => application/pdf
    [pathName:SplFileInfo:private] => /tmp/phpFe5R0e
    [fileName:SplFileInfo:private] => phpFe5R0e
)

But when I try to get its mimetype, it returns an unrelated value:

$mimetype = \File::mimeType($file);
\Log::debug($mimetype);
// testing.DEBUG: filemimetyperule = inode/x-empty

In the case of a JPG image I even get png/image.

Is it wrong to use \File::mimeType() to access the mimetype of an uploaded file?

Edit: After a look in the Laravel API, I changed my validation code to $value->getMimeType() and as far this method is doing fine with fake and real uploads.

lostdreamer_nl

\File::mimeType() goes to:

finfo_file(finfo_open(FILEINFO_MIME_TYPE), $path);

Actually checking the file's path (which will be a temp file on the disk after upload)

Try using this one, it simply uses the filename you give without checking the filesystem:

    dd( \Illuminate\Http\Testing\MimeType::from('test.pdf') );


    dd( \Illuminate\Http\Testing\MimeType::from( $file->name ) );


Please sign in or create an account to participate in this conversation.