manually creating an Symfony UploadedFile - php

I'm facing following problem and can't seem to figure this one out.
I wrote an API endpoint accepting a POST with binary data (header: content-type:image/jpeg).
I know i can read out the raw string with file_get_content('php://input') or Laravel's $request->getContent().
PHP also has a function createimagefromstring($string) which also seems to read the string in correctly.
What i'd like to do is create an UploadedFile from this raw data , so that I can handle it with already written functions.
Is this possible?
Thank you in advance

I think I found it... Still curious if there are improvements that can be made..
$imgRaw = imagecreatefromstring( $request->getContent() );
if ($imgRaw !== false) {
imagejpeg($imgRaw, storage_path().'/tmp/tmp.jpg',100);
imagedestroy($imgRaw);
$file = new UploadedFile( storage_path().'/tmp/tmp.jpg', 'tmp.jpg', 'image/jpeg',null,null,true);
// DO STUFF WITH THE UploadedFile
}

You can try to use base64 encoding. Symfony have some nice stuff for this.
Your code will be smthng like this:
$base64Content = $request->request->get('base64Content'); // this is your post data
$yourFile = new UploadedBase64EncodedFile(new Base64EncodedFile($base64Content)); // this is an instance of UploadedFile
Hope it helps!

As per Laravel 8
Just follow the constructor:
* #param string $path The full temporary path to the file
* #param string $originalName The original file name of the uploaded file
* #param string|null $mimeType The type of the file as provided by PHP; null defaults to application/octet-stream
* #param int|null $error The error constant of the upload (one of PHP's UPLOAD_ERR_XXX constants); null defaults to UPLOAD_ERR_OK
* #param bool $test Whether the test mode is active
$file = new UploadedFile(
$pathIncludingFilename,
$fileName,
'image/jpeg',
null,
false
);

There is no need to manually create it, Symfony parses received $_FILES array for you. Http Request object has a FileBag property called $files with a get() method which returns an UploadedFile instance.
/** #var UploadedFile $file */
$file = $request->files->get('user-pictures-upload')[0];
$cmd = new UploadPictureCmd($file, $this->getUser()->getId());

Here is the example of generating images files using fzaninotto/faker in Symfony 4 Fixtures
class FileFixtures extends Fixture
{
private $faker;
private $parameterBag;
public function __construct(ParameterBagInterface $parameterBag)
{
$this->faker = Factory::create();
$this->parameterBag = $parameterBag;
}
public function load(ObjectManager $manager)
{
$tempFixturesPath = $this->parameterBag->get('kernel.project_dir') . '/tmp';
if (!file_exists($tempFixturesPath)) {
mkdir($tempFixturesPath);
}
$fileName = $this->faker->image($tempFixturesPath, 640, 480, 'cats', false, true);
$file = new UploadedFile($tempFixturesPath . '/' . $fileName, $fileName, 'image/jpeg', null, null, true);
//do something with $file
}
}

If it counts for anything, this is how I did it in Laravel 5.4. In my case, I wanted to be able to easily resize an image and be able to do something like this.
request()->file('image')->resize(250, 250)->store('path/to/storage');
This is what I did to the UploadedFile class.
Illuminate\Http\UploadedFile.php ~this file ships with the Laravel framework
public function resize($w, $h) {
$image = Intervention::make($this)->fit($w, $h)->save($this->getPathname());
$filesize = filesize($this->getPathname());
return new static(
$this->getPathname(),
$this->getClientOriginalName(),
$this->getClientMimeType(),
$filesize,
null,
false
);
}
Using Intervention, I resized the image that is stored in the /tmp/ folder when files are uploaded and then I saved it in the same place. Now all I do after that is create an instance of UploadedFile so that I can keep using Laravel's methods on request()->file('image'). Hope this helps.

Related

Turn a files content into an UploadedFile

I have a file saved in my application whose content I would like to create a laravel UploadedFile with.
$content = file_get_contents(storage_path('app/Imports/example.csv'));
// returns Illuminate\Http\UploadedFile;
$uploadedFile = $this->someMethodToMakeLaravelUploadedFile($content);
How can I achieve this?
You can make a new Uploadedfile
use Illuminate\Http\UploadedFile;
return new UploadedFile($path, $name);
In your case
$uploadedFile = new UploadedFile(storage_path('app/Imports/example.csv')), 'example.csv')

remove Exiff from UploadedFile Symfony

I have form that use to upload picture.
I can't save this picture on my server, But I send it to another service ( external)
I have to encode base 64
my code is:
$base_img = base64_encode(file_get_contents($data["image"]));
where $data['image'] is UploadedFile
How can Remove all Exiff from $data['image'] before encode?
Recently I needed exactly that and I achieved it with passing $uploadedFile->getRealPath() to the Imagick. Complete function:
/**
* #param UploadedFile $uploadedFile
* #throws \ImagickException
*/
public function stripMeta(UploadedFile $uploadedFile): void
{
$img = new Imagick($uploadedFile->getRealPath());
$profiles = $img->getImageProfiles("icc", true);
$img->stripImage();
if(!empty($profiles)) {
$img->profileImage("icc", $profiles['icc']);
}
$img->writeImage($uploadedFile->getRealPath());
}
I took saving icc profile idea from comments here: https://www.php.net/manual/en/imagick.stripimage.php

XenForo Avatar upload fails, $image == false - PHP7

I'm stumped on a XenForo 1.5.7 / php7 issue. I've read that tempnam() was changed as of php7 (based on temp dir permissions), but I've chmod'd the directory as that link states, still to no avail.
I printed out $newTempFile which returns /var/www/forum/internal_data/temp/xfJ9FLyG (looks correct). It's the next line, the $image variable, that does not get set, and then throws the error in the if() below.
$newTempFile = tempnam(XenForo_Helper_File::getTempDir(), 'xf');
$image = XenForo_Image_Abstract::createFromFile($fileName, $imageType);
if (!$image)
{
throw new XenForo_Exception(new XenForo_Phrase('image_could_be_processed_try_another_contact_owner'), true);
}
Here is the code for createFromFile() in Image\Abstract.php:
/**
* Creates an image from an existing file.
*
* #param string $fileName
* #param integer $inputType IMAGETYPE_XYZ constant representing image type
*
* #return XenForo_Image_Abstract|false
*/
public static function createFromFileDirect($fileName, $inputType)
{
throw new XenForo_Exception('Must be overridden');
}
...
public static function createFromFile($fileName, $inputType)
{
$class = self::_getDefaultClassName();
return call_user_func(array($class, 'createFromFileDirect'), $fileName, $inputType);
}
Because it looks like createFromFileDirect() is called from createFromFile(), my thought was that a "Must be overriden" error would be thrown, but this doesn't appear to be the case.
Any ideas?

How to make UploadedFile invalid for UnitTest?

I am making a test for uploading a file in Laravel 5.1 project.
One of the checking in validation method looks like this
//assuming $file is instance of UploadedFile class
if ( ! $file->isValid()) {
/*add errors and return*/
}
And I need to test this check.
The question is: How do I create an invalid uploaded file ?
(UploadedFile extends Symfony\Component\HttpFoundation\File class which extends SplFileInfo php class)
I often find it's helpful to look at the library source:
https://github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpFoundation/File/UploadedFile.php
You can see that the isValid method checks if $this->error === UPLOAD_ERR_OK, which is the default.
The only way to set error, since it's a private variable, is through the constructor:
public function __construct($path, $originalName, $mimeType = null, $size = null, $error = null, $test = false)
So when creating your $file object, just make sure to set $error to something. Here's all of the available error constants:
http://php.net/manual/en/features.file-upload.errors.php
So for example you could do this:
$file = new UploadedFile($path, $origName, $mimeType, UPLOAD_ERR_INI_SIZE, true);
The last parameter is needed when testing to disable checking that file was uploaded via HTTP (in case your test actually creates file)

Laravel 5 & Mamp - stores weird path when uploading a file

/**
* Store a newly created resource in storage.
*
* #param Request $request
* #return Response
*/
public function store(AdminProgramRequest $request)
{
$request = $this->move_image_file($request, 'thumbnail');
$request = $this->move_image_file($request, 'korean_brochure');
$request = $this->move_image_file($request, 'english_brochure');
$request = $this->move_image_file($request, 'chinese_brochure');
Program::create($request->all());
return redirect('dashboard/program_category/'.$request->program_category_id.'/edit');
}
private function move_image_file($request, $input_name)
{
if($request->hasFile($input_name)){
$filename = $request->file($input_name)->getClientOriginalName();
$request->file($input_name)->move(
base_path() . '/public/pdf/program_category/' . $request->program_category_id . '/' , $filename
);
$request->merge([
// I think this is where
// /private/var/folders/_l/9jdb6p2s3ms4vh8jv0mp_43w0000gn/T/phphi95xw
// stuff gets stored in $request even if
// $filename has the uploaded filename for sure.
$input_name => $filename
// This hardcode also works in the same way and stores weird path in db... WHY!?
// $input_name => 'whats_going_on.jpg'
]);
}
return $request;
}
This is driving me nuts. I'm pretty sure that $filename has the filename of the uploaded file.
I've double checked if $filename has a correct value. Yes.
I've hardcoded and given a randome filename to $filname. Still doesn't work but stores the weird path thing.
I've tested if files are being uploaded correctly. and Yes.
I've checked view files. Since #3 is working, of course Yes.
Now, I'm suspecting MAMP.
Has anyone experienced the same issue with Laravel5 and Mamp on OSX?

Categories