Rename image and then save image name into database - php

I want to get image from the user and then rename it and after that i want to save the renamed image name into the database. here is my controller codes. im using intervention package. i can save the photo to the destination folder correctly after renaming it but i cant save the name of the photo into my database after renaming. what will be the code?
public function store(UserRequest $request)
{
$farmer = User::create([
'name' => $request->name,
'phone' => $request->phone,
'address' => $request->address,
'nid' => $request->nid,
'dob' => $request->dob,
'remarks' => $request->remarks,
'division_id' => $request->division_id,
'district_id' => $request->district_id,
'upazila_id' => $request->upazila_id,
'farmer_point_id' => $request->farmer_point_id,
'user_type_id' => 3 // 3 is for farmer
]);
$image = Image::make($request->profile_picture);
$image->resize(250, 272);
$image->save(public_path("uploads/Farmers/farmer_$farmer->id.jpg"));
return redirect("farmer/{$farmer->id}");
}

The ideal thing to do is to upload the image first and then save the file path to database.
Ideally, it will be better to extract your upload logic into a separate stand-alone class. You can use use the below as a guide.
<?php
Class UploadImage
{
/**
* UploadPostImage constructor.
* .
* #param UploadedFile $postedImage
*
*/
public function __construct(UploadedFile $postedImage)
{
$this->postedImage = $postedImage;
}
/**
* Create the filename
*
*/
public function getFilename()
{
$dt = Carbon::now();
$timestamp = $dt->getTimestamp();
$this->filename = $timestamp . '_' . $this->postedImage->getClientOriginalName();
}
/**
* Create the image and return the path
*
* #param $path
* #param int $width
* #return mixed
*/
public function createImage($path, $width = 400)
{
// Upload the image
$image = Image::make($this->postedImage)
->resize(250, 272);
$image->save(public_path($path . $this->filename, 60));
return $path . $this->filename;
}
}
In your controller, you can then call this class
$uploadImage = new Image(UploadedFile $file);
$uploadImage->getFilename();
$data['image'] = uploadImage->createImage('your-upload-path');
// Add other data into the $data array, then save to database.
$data['phone'] = $request->name,
$data['address'] = $request->address
// Add other data then pass it into User::create()
When you make a call to createImage() in your controller, the path is returned to you and you can save this in your database.
I hope this helps!

Related

validating base64 image laravel

Im saving a request to my database from my vue js via;
public function store(Request $request)
{
//validate
$this->validate($request, [
'name' => 'required',
'description' => 'required',
'price' => 'required'
]);
//get image
$exploded = explode(',', $request->cover_image);
$decoded = base64_decode($exploded[1]);
if(str_contains($exploded[0],'jpeg'))
$extension = 'jpg';
else
$extension = 'png';
$fileName = str_random().'.'.$extension;
$path = public_path().'/cover_images/'.$fileName;
file_put_contents($path, $decoded);
//save
$product = new Product;
$product->name = $request->input('name');
$product->description = $request->input('description');
$product->price = $request->input('price');
$product->cover_image = $fileName;
if($product->save()) {
return new ProductsResource($product);
}
}
How can I validate the base64 image? Is my procedure in saving the image coming from vue js is in correct way or is there a better way? please let me know. Thanks im just new to laravel and vue js hoping to learn more
You should add this function to your custom helper :
if (!function_exists('validate_base64')) {
/**
* Validate a base64 content.
*
* #param string $base64data
* #param array $allowedMime example ['png', 'jpg', 'jpeg']
* #return bool
*/
function validate_base64($base64data, array $allowedMime)
{
// strip out data uri scheme information (see RFC 2397)
if (strpos($base64data, ';base64') !== false) {
list(, $base64data) = explode(';', $base64data);
list(, $base64data) = explode(',', $base64data);
}
// strict mode filters for non-base64 alphabet characters
if (base64_decode($base64data, true) === false) {
return false;
}
// decoding and then reeconding should not change the data
if (base64_encode(base64_decode($base64data)) !== $base64data) {
return false;
}
$binaryData = base64_decode($base64data);
// temporarily store the decoded data on the filesystem to be able to pass it to the fileAdder
$tmpFile = tempnam(sys_get_temp_dir(), 'medialibrary');
file_put_contents($tmpFile, $binaryData);
// guard Against Invalid MimeType
$allowedMime = array_flatten($allowedMime);
// no allowedMimeTypes, then any type would be ok
if (empty($allowedMime)) {
return true;
}
// Check the MimeTypes
$validation = Illuminate\Support\Facades\Validator::make(
['file' => new Illuminate\Http\File($tmpFile)],
['file' => 'mimes:' . implode(',', $allowedMime)]
);
return !$validation->fails();
}
}
Then extend the base64_image validation in your AppServiceProvider in boot() method :
use Illuminate\Support\Facades\Validator;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap services.
*
* #return void
*/
public function boot()
{
...
Validator::extend('base64_image', function ($attribute, $value, $parameters, $validator) {
return validate_base64($value, ['png', 'jpg', 'jpeg', 'gif']);
});
}
Now you can use it in your validation rules like this :
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'photo' => 'required|base64_image'
];
}
There is a crazybooot/base64-validation package that handles base64 validation.
For installation instructions and more details see:
https://github.com/crazybooot/base64-validation

Laravel 5.4 GIF Images are saved "statically"

I am working on this Laravel 5.4 Social Network Script and when I post something the avatar is being displayed "animated" but when it is being saved it is converted to an static image.
I have this in the controller TimelineController#createPost:
...
use App\Media;
use App\Post;
use Intervention\Image\Facades\Image;
...
public function createPost(Request $request)
{
$input = $request->all();
$post = Post::create($input);
...
if ($request->file('post_images_upload_modified')) {
foreach ($request->file('post_images_upload_modified') as $postImage) {
$strippedName = str_replace(' ', '', $postImage->getClientOriginalName());
$photoName = date('Y-m-d-H-i-s').$strippedName;
$avatar = Image::make($postImage->getRealPath());
$avatar->save(storage_path().'/uploads/users/gallery/'.$photoName, 60);
$media = Media::create([
'title' => $photoName,
'type' => 'image',
'source' => $photoName,
]);
$post->images()->attach($media);
}
}
...
}
...
It uses GD Library to process the images internally.
The file Image.php on /vendor/intervention/image/src/Intervention/Image/:
#method \Intervention\Image\Image make(mixed $source) Universal factory method to create a new image instance from source, which can be a filepath, a GD image resource, an Imagick object or a binary image data.
/**
* Starts encoding of current image
*
* #param string $format
* #param integer $quality
* #return \Intervention\Image\Image
*/
public function encode($format = null, $quality = 90)
{
return $this->driver->encode($this, $format, $quality);
}
/**
* Saves encoded image in filesystem
*
* #param string $path
* #param integer $quality
* #return \Intervention\Image\Image
*/
public function save($path = null, $quality = null)
{
$path = is_null($path) ? $this->basePath() : $path;
if (is_null($path)) {
throw new Exception\NotWritableException(
"Can't write to undefined path."
);
}
$data = $this->encode(pathinfo($path, PATHINFO_EXTENSION), $quality);
$saved = #file_put_contents($path, $data);
if ($saved === false) {
throw new Exception\NotWritableException(
"Can't write image data to path ({$path})"
);
}
// set new file info
$this->setFileInfoFromPath($path);
return $this;
}
The stored image is a GIF but resized despite it is not specified:
Do you know how to make the image animated when saved?

How to create a file upload REST API controller for Yii2

I am using Ionic framework for mobile app development. The Yii2 API code below can be used for file upload, but it doesn't work. It shows the following errors:
i) Undefined offset: 0.
ii) yii\db\BaseActiveRecord->save()
public function actionNew() {
$model = new Apiprofile();
$userid = $_REQUEST['user_id'];
$photo = $_FILES['photo'];
$model->user_id = $userid;
$model->photo = $photo;
$name = $model->user_id;
$model->file = UploadedFile::getInstance($model, 'photo');
if($model->file) {
$model->file->saveAs('uploads/photos/'.$name.'.'.$model->file->extension);
$model->photo = $name.'.'.$model->file->extension;
$model->save();
}
$name = $model->user_id;
if($model->save()) {
echo json_encode(array('status'=>1,'data'=>$model->attributes),JSON_PRETTY_PRINT);
} else {
echo json_encode(array('status'=>0,'error_code'=>400,'errors'=>$model->errors),JSON_PRETTY_PRINT);
}
}
Hi if you want I will share my helper class that I used for working with images in Yii2 REST.
In the base folder of your application create folder components and inside of that folder create two folders helpers and objects.
-->assets
-->componests
----->helpers
----->objects
-->config
-->...
after that create class FileUpload inside of objects folder and put this code inside.
<?php
namespace app\components\objects;
class FileUpload
{
public $error=[];
public $isSuccess=false;
public $file;
public $ready_path;
public $file_type;
public $file_size;
public $file_extension;
public $file_tmp_name;
public $file_name;
public $save_path;
public function __construct($file,$save_path,$ready_path,$required=false)
{
if(!isset($_FILES[$file])){
if($required){
$this->error=['message'=>$file.' is required'];
}
return $this;
}
$this->save_path=$save_path;
$this->ready_path=$ready_path;
$this->file_type = strtolower($_FILES[$file]['type']);
$this->file_name = $_FILES[$file]['name'];
$this->file_tmp_name=$_FILES[$file]['tmp_name'];
$this->file_size = $_FILES[$file]['size'];
$this->file_extension=pathinfo($this->file_name, PATHINFO_EXTENSION);
}
public function setError($error){
if(empty($this->error)){
$this->error=$error;
}
}
}
Then inside of helpers folder create class FileUploadHelper and then put this code inside.
<?php
namespace app\components\helpers;
use app\components\objects\FileUpload;
use Yii;
class FileUploadHelper
{
private $allowed_files;
private $file_size;
const IMAGE='image';
const FILE='file';
/** File Upload
* #param string $file_name
* #param string $save_path
* #param string $ready_path
* #param string $type
* #param bool $required
* #return \app\components\objects\FileUpload
*/
public static function fileUpload($file_name,$save_path,$ready_path,$type,$required=false){
$image=new FileUpload($file_name,$save_path,$ready_path,$required);
if($type==self::FILE){
$allowed_files=Yii::$app->params['allowed_files'];
$file_size=Yii::$app->params['file_max_size'];
}else{
$allowed_files=Yii::$app->params['allowed_files'];
$file_size=Yii::$app->params['file_max_size'];
}
$dir = realpath(Yii::$app->basePath);
if(in_array($image->file_type,$allowed_files)
&&$image->file_size<$file_size){
$filename = $file_name.'_'.md5(uniqid(time()).time() . '_' . date('YmdHis')) . '.' . $image->file_extension;
$file = $dir . $image->save_path . $filename;
if(move_uploaded_file($image->file_tmp_name, $file)){
$image->file=$image->ready_path. $filename;
$image->isSuccess=true;
$image->setError(['message'=>'file_upload_success']);
}else{
$image->setError(['message'=>'error_try_again']);
}
}else{
$image->setError(['message'=>'file_should_be_no_more_than_given_size']);
}
return $image;
}
/** Delete File
* #param string $ready_file
*/
public static function deleteImage($ready_file){
$dir = realpath(Yii::$app->basePath);
if (strpos($ready_file, 'default') === false){
if(is_file($dir.'/web/'.$ready_file)){
unlink($dir.'/web/'.$ready_file);
}
}
}
}
That's all needed. Below I will give you example
public function actionEditAvatar($id)
{
$product = Product::findOne($id);
if( $product ){
$old_avatar=$product->avatar;
$image=FileUploadHelper::fileUpload(ProductForm::AVATAR,Yii::$app->params['product_path'],Yii::$app->params['product_ready_path'],FileUploadHelper::IMAGE);
if($image->isSuccess) {
$product->avatar = $image->file;
if($product->save()){
FileUploadHelper::deleteImage($old_avatar);
return $product->avatar;
}
}
return $image->error;
}
throw new NotFoundHttpException;
}
The code above from a real project. FileUploadHelper has two static classes which are "fileUpload" and "deleteImage".
FileUploadHelper requires fileUpload('file_name','save_path','ready_path','type')
'save_path' is where the file will be saved.
'ready_path' is how the ready URL should be like.
they are in Yii::$app->params[];
You can check if image succeeded or not by attribute isSuccess. If you have the error you can access them by attribute error. The ready file can be accessed by attribute file. You can delete image via static function deleteImage('saved_image_url'); All of them are used at above action. Please see it.
By the way, here the params that I used. Do not forget to to create folders inside web/uploads and change names of the folders like in config file.
return [
'adminEmail' => 'admin#example.com',
'allowed_images' => [ 'image/jpeg', 'image/gif', 'image/png' ],
'allowed_files' => [ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document','application/msword', 'application/pdf','image/jpeg', 'image/gif', 'image/png'],
'image_max_size' => 2097152,
'file_max_size' => 8388608,
'owner_document_path' => '/web/uploads/owner_document/',
'owner_document_ready_path' => 'uploads/owner_document/',
'product_path' => '/web/uploads/product/',
'product_ready_path' => 'uploads/product/',
'complain_photo_path' => '/web/uploads/complain_photo/',
'complain_photo_ready_path' => 'uploads/complain_photo/',
'owner_path' => '/web/uploads/owner/',
'owner_ready_path' => 'uploads/owner/',
'staff_path' => '/web/uploads/staff/',
'staff_ready_path' => 'uploads/staff/',
];

How to test file upload in Laravel 5.2

Im trying to test an upload API but it fails every time:
Test Code :
$JSONResponse = $this->call('POST', '/upload', [], [], [
'photo' => new UploadedFile(base_path('public/uploads/test') . '/34610974.jpg', '34610974.jpg')
]);
$this->assertResponseOk();
$this->seeJsonStructure(['name']);
$response = json_decode($JSONResponse);
$this->assertTrue(file_exists(base_path('public/uploads') . '/' . $response['name']));
file path is /public/uploads/test/34610974.jpg
Here is My Upload code in a controller :
$this->validate($request, [
'photo' => 'bail|required|image|max:1024'
]);
$name = 'adummyname' . '.' . $request->file('photo')->getClientOriginalExtension();
$request->file('photo')->move('/uploads', $name);
return response()->json(['name' => $name]);
How should I test file upload in Laravel 5.2? How to use call method to upload a file?
When you create an instance of UploadedFile set the last parameter $test to true.
$file = new UploadedFile($path, $name, filesize($path), 'image/png', null, true);
^^^^
Here is a quick example of a working test. It expects that you have a stub test.png file in tests/stubs folder.
class UploadTest extends TestCase
{
public function test_upload_works()
{
$stub = __DIR__.'/stubs/test.png';
$name = str_random(8).'.png';
$path = sys_get_temp_dir().'/'.$name;
copy($stub, $path);
$file = new UploadedFile($path, $name, filesize($path), 'image/png', null, true);
$response = $this->call('POST', '/upload', [], [], ['photo' => $file], ['Accept' => 'application/json']);
$this->assertResponseOk();
$content = json_decode($response->getContent());
$this->assertObjectHasAttribute('name', $content);
$uploaded = 'uploads'.DIRECTORY_SEPARATOR.$content->name;
$this->assertFileExists(public_path($uploaded));
#unlink($uploaded);
}
}
➔ phpunit tests/UploadTest.php
PHPUnit 4.8.24 by Sebastian Bergmann and contributors.
.
Time: 2.97 seconds, Memory: 14.00Mb
OK (1 test, 3 assertions)
In Laravel 5.4 you can also use \Illuminate\Http\UploadedFile::fake(). A simple example below:
/**
* #test
*/
public function it_should_allow_to_upload_an_image_attachment()
{
$this->post(
action('AttachmentController#store'),
['file' => UploadedFile::fake()->image('file.png', 600, 600)]
);
/** #var \App\Attachment $attachment */
$this->assertNotNull($attachment = Attachment::query()->first());
$this->assertFileExists($attachment->path());
#unlink($attachment->path());
}
If you want to fake a different file type you can use
UploadedFile::fake()->create($name, $kilobytes = 0)
More information directly on Laravel Documentation.
I think this is the easiest way to do it
$file=UploadedFile::fake()->image('file.png', 600, 600)];
$this->post(route("user.store"),["file" =>$file));
$user= User::first();
//check file exists in the directory
Storage::disk("local")->assertExists($user->file);
and I think the best way to delete uploaded files in the test is by using tearDownAfterClass static method,
this will delete all uploaded files
use Illuminate\Filesystem\Filesystem;
public static function tearDownAfterClass():void{
$file=new Filesystem;
$file->cleanDirectory("storage/app/public/images");
}
The laravel documentation has an answer for when you want to test a fake file. When you want to test using a real file in laravel 6 you can do the following:
namespace Tests\Feature;
use Illuminate\Http\UploadedFile;
use Tests\TestCase;
class UploadsTest extends TestCase
{
// This authenticates a user, useful for authenticated routes
public function setUp(): void
{
parent::setUp();
$user = User::first();
$this->actingAs($user);
}
public function testUploadFile()
{
$name = 'file.xlsx';
$path = 'absolute_directory_of_file/' . $name;
$file = new UploadedFile($path, $name, 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', null, true);
$route = 'route_for_upload';
// Params contains any post parameters
$params = [];
$response = $this->call('POST', $route, $params, [], ['upload' => $file]);
$response->assertStatus(200);
}
}
You can find this code at this link
Setup
/**
* #param $fileName
* #param $stubDirPath
* #param null $mimeType
* #param null $size
*
* #return \Illuminate\Http\UploadedFile
*/
public static function getTestingFile($fileName, $stubDirPath, $mimeType = null, $size = null)
{
$file = $stubDirPath . $fileName;
return new \Illuminate\Http\UploadedFile\UploadedFile($file, $fileName, $mimeType, $size, $error = null, $testMode = true);
}
Usage
$fileName = 'orders.csv';
$filePath = __DIR__ . '/Stubs/';
$file = $this->getTestingFile($fileName, $filePath, 'text/csv', 2100);
Folder Structure:
- MyTests
- TestA.php
- Stubs
- orders.csv

Zend From file upload not working

I'm having some issues uploading a file using Zend Framework. I have created a form, listed below, and have passed the data input to my model where I am attempting to upload the file. IT seems only to get the file name however and fails to upload to my uploads directory.
Form
<?php
class Application_Form_Admin extends Zend_Form
{
public function init()
{
// Set the method for the display form to POST
$this->setMethod('post');
// set the data format
$this->setAttrib('enctype', 'multipart/form-data');
// Add the title
$this->addElement('file', 'ogimage', array(
'label' => 'Default App Image',
'required' => false
));
// Add the submit button
$this->addElement('submit', 'submit', array(
'ignore' => true,
'label' => 'Submit',
));
// And finally add some CSRF protection
$this->addElement('hash', 'csrf', array(
'ignore' => true,
));
}
}
Controller
<?php
class AdminController extends Zend_Controller_Action
{
/**
* #var The Admin Model
*
*
*/
protected $app = null;
/**
* init function.
*
* #access public
* #return void
*
*
*/
public function init()
{
// get the model
$this->app = new Application_Model_Admin();
}
/**
* indexAction function.
*
* #access public
* #return void
*
*
*/
public function indexAction()
{
// get a form
$request = $this->getRequest();
$form = new Application_Form_Admin();
// pre populate form
$form->populate((array) $this->app->configData());
// handle form submissions
if($this->getRequest()->isPost()) {
if($form->isValid($request->getPost())) {
// save the clips
$this->app->saveConfig($form);
// redirect
//$this->_redirect('/admin/clips');
}
}
// add the form to the view
$this->view->form = $form;
}
}
Model
class Application_Model_Admin
{
/**
* #var Bisna\Application\Container\DoctrineContainer
*/
protected $doctrine;
/**
* #var Doctrine\ORM\EntityManager
*/
protected $entityManager;
/**
* #var ZC\Entity\Repository\FacebookConfig
*/
protected $facebookConfig;
/**
* Constructor
*/
public function __construct(){
// get doctrine and the entity manager
$this->doctrine = Zend_Registry::get('doctrine');
$this->entityManager = $this->doctrine->getEntityManager();
// include the repository to get data
$this->facebookConfig = $this->entityManager->getRepository('\ZC\Entity\FacebookConfig');
}
/**
* saveConfig function.
*
* #access public
* #param mixed $form
* #return void
*/
public function saveConfig($form){
// get the entity
$config = new \ZC\Entity\FacebookConfig();
// get the values
$values = $form->getValues();
// upload the file
$upload = new Zend_File_Transfer_Adapter_Http();
$upload->setDestination(APPLICATION_PATH . '/../uploads/');
try {
// upload received file(s)
$upload->receive();
} catch (Zend_File_Transfer_Exception $e) {
$e->getMessage();
}
// get some data about the file
$name = $upload->getFileName($values['ogimage']);
$upload->setOptions(array('useByteString' => false));
//$size = $upload->getFileSize($values['ogimage']);
//$mimeType = $upload->getMimeType($values['ogimage']);
print_r('<pre>');var_dump($name);print_r('</pre>');
//print_r('<pre>');var_dump($size);print_r('</pre>');
//print_r('<pre>');var_dump($mimeType);print_r('</pre>');
die;
// following lines are just for being sure that we got data
print "Name of uploaded file: $name
";
print "File Size: $size
";
print "File's Mime Type: $mimeType";
// New Code For Zend Framework :: Rename Uploaded File
$renameFile = 'file-' . uniqid() . '.jpg';
$fullFilePath = APPLICATION_PATH . '/../uploads/' . $renameFile;
// Rename uploaded file using Zend Framework
$filterFileRename = new Zend_Filter_File_Rename(array('target' => $fullFilePath, 'overwrite' => true));
$filterFileRename->filter($name);
// loop through the clips and add to object
foreach($values as $k => $column){
$config->__set($k, $column);
}
// save or update the clips object
if(empty($values['id'])){
$this->entityManager->persist($config);
} else {
$this->entityManager->merge($config);
}
// execute the query
$this->entityManager->flush();
// set the id
$form->getElement('id')->setValue($config->__get('id'));
}
}
The issue was that I was accessing the form data before the upload with the following line:
// get the values
$values = $form->getValues();
This is now placed after the upload in the model and the file data is accessed instead with the following:
$file = $upload->getFileInfo();
You have to move the file to where you want it. Here is a small snippet that I use in my code
if($form->isValid($request->getPost())) {
$uploadedFile = new Zend_File_Transfer_Adapter_Http();
$uploadedFile->setDestination(APPLICATION_PATH.'/../public_uploads/');
if($uploadedFile->receive()) {
//Code to process the file goes here
} else {
$errors = $uploadedFile->getErrors();
}
$this->app->saveConfig($form);
}
Hope this helps you get started.
to make this work you need to set setValueDisabled = true in your form element otherwise as soon as you call $form->getValues() it will upload the file to the system temp folder.
Currently you are calling $form->getValues() before you are even setting the destination so the file goes to the default (system temp).

Categories