I have an upload form, it works well, the photo is being uploaded but the problem is that the sfThumbnail plugin doesn't seem to work. No thumbnail is being generated. Here's my code:
// /lib/form/UploadForm.class.php
public function configure()
{
$this->setWidget('photo', new sfWidgetFormInputFileEditable(
array(
'edit_mode' => !$this->isNew(),
'with_delete' => false,
'file_src' => '',
)
));
$this->widgetSchema->setNameFormat('image[%s]');
$this->setValidator('photo', new sfValidatorFile(
array(
'max_size' => 5000000,
'mime_types' => 'web_images',
'path' => '/images/',
'required' => true,
'validated_file_class' => 'sfMyValidatedFileCustom'
)
));
And here's for the validator class
class sfMyValidatedFileCustom extends sfValidatedFile{
public function save($file = null, $fileMode = 0666, $create = true, $dirMode = 0777)
{
$saved = parent::save($file, $fileMode, $create, $dirMode);
$thumbnail = new sfThumbnail(150, 150, true, true, 75, '');
$location = strpos($this->savedName,'/image/');
$filename = substr($this->savedName, $location+15);
// Manually point to the file then load it to the sfThumbnail plugin
$uploadDir = sfConfig::get('sf_root_dir').'/image/';
$thumbnail->loadFile($uploadDir.$filename);
$thumbnail->save($uploadDir.'thumb/'.$filename,'image/jpeg');
return $saved;
}
And my actions code:
public function executeUpload(sfWebRequest $request)
{
$this->form = new UploadForm();
if ($request->isMethod('post'))
{
$this->form->bind(
$request->getParameter($this->form->getName()),
$request->getFiles($this->form->getName())
);
if ($this->form->isValid())
{
$this->form->save();
return $this->redirect('photo/success');
}
}
}
I'm not 100% sure if I am doing it correctly but this is what I have seen from the docs and other examples.
You can't use $this->savedName because it's a protected value from sfValidatedFile. You should use $this->getSavedName() instead.
I don't understand this part:
$location = strpos($this->savedName,'/image/');
$filename = substr($this->savedName, $location+15);
Why do you extract the filename, when, finally, you re-add /image/ to it when load it with loadFile?
Any way, I made some change on your class. I didn't tested it but I think it should work.
class sfMyValidatedFileCustom extends sfValidatedFile
{
public function save($file = null, $fileMode = 0666, $create = true, $dirMode = 0777)
{
$saved = parent::save($file, $fileMode, $create, $dirMode);
$filename = str_replace($this->getPath().DIRECTORY_SEPARATOR, '', $saved);
// Manually point to the file then load it to the sfThumbnail plugin
$uploadDir = $this->getPath().DIRECTORY_SEPARATOR;
$thumbnail = new sfThumbnail(150, 150, true, true, 75, '');
$thumbnail->loadFile($uploadDir.$saved);
$thumbnail->save($uploadDir.'thumb/'.$filename, 'image/jpeg');
return $saved;
}
Related
Is it possible to pass data from seeder to factory?
This is my PictureFactory:
class PictureFactory extends Factory{
protected $model = Picture::class;
public function definition($galleryId = null, $news = false){
if (!is_null($galleryId)){
$galley = Gallery::find($galleryId);
$path = 'public/galleries/' . $galley->name;
$newsId = null;
}
if ($news){
$path = 'public/newsPicture';
$newsId = News::all()->random(1);
}
$pictureName = Faker::word().'.jpg';
return [
'userId' => 1,
'src' =>$this->faker->image($path,400,300, 2, false) ,
'originalName' => $pictureName,
'newsId' => $newsId
];
}
}
and I use it like this in database seeder:
News::factory(3)
->has(Comment::factory()->count(2), 'comments')
->create()
->each(function($news) {
$news->pictures()->save(Picture::factory(null, true)->count(3));
});
but $galleryId and $news do not pass to PictureFactory. Where did I go wrong? And what should I do? please help me.
This is the sort of thing that factory states were made for. Assuming you are using a current (8.x) version of Laravel, define your factory like this:
<?php
namespace Database\Factories\App;
use App\Models\{Gallery, News, Picture};
use Illuminate\Database\Eloquent\Factories\Factory;
class PictureFactory extends Factory
{
protected $model = Picture::class;
public function definition()
{
return [
'userId' => 1,
'originalName' => $this->faker->word() . '.jpg',
];
}
public function withGallery($id)
{
$gallery = Gallery::findOrFail($id);
$path = 'public/galleries/' . $gallery->name;
return $this->state([
'src' => $this->faker->image($path, 400, 300, 2, false),
'newsId' => null,
]);
}
public function withNews()
{
$news = News::inRandomOrder()->first();
$path = 'public/newsPicture';
return $this->state([
'src' => $this->faker->image($path, 400, 300, 2, false),
'newsId' => $news->id,
]);
}
}
And now you can create your desired models like this:
Picture::factory()->count(3)->withNews();
// or
Picture::factory()->count(3)->withGallery($gallery_id);
I'm not certain, but I believe you should be able to do this to get your desired outcome:
Picture::factory()
->count(3)
->withNews()
->for(News::factory()->hasComments(2))
->create();
I am using kartik fileUpload extension for uploading of files in yii2, As soon as i select a file and submit, im getting
Call to a member function saveAs() on a non-object
I have checked other post regarding this issue but its not helping,
My View code..
<?php echo $form->field($documents, 'sars_certificate')->label(false)->
widget(FileInput::classname(), [
'pluginOptions' => [
'showCaption' => true,'showRemove' => true,'showClose' => true,
'showPreview' => true,'uploadAsync' => true,
'showUpload' => false,'maxFileSize'=> 2000,'autoReplace'=> true,
'placeholder' => 'Select a File...',],]); ?>
My model code..
[['sars_certificate'], 'file', 'skipOnEmpty' => false, 'extensions' => 'png, jpg,pdf,jpeg']
And My controller code..
public function actionCreate()
{
$model = new Projects();
$documents = new ProjectDocuments();
$borrower_id = Yii::$app->user->identity->id;
$code = $model->accessCode(10);
if ($model->load(Yii::$app->request->post()))
{
//All $model related things will bw done
//In this im doing file upload
$documents->borrower_id = $borrower_id;
$documents->project_id = $code;
$documents->save(false);
$documents->sars_certificate = UploadedFile::getInstances($documents,'sars_certificate');
$documents->sars_certificate->saveAs('user/purchase_order/' . $documents->sars_certificate->baseName . '.' . $documents->sars_certificate->extension);
$documents->sars_certificate = $documents->sars_certificate;
$documents->save(false);
return $this->redirect(['index']);
}
I have given if($documents->validate()){ **** }. But its not coming under if condition itself, so i removed it. Now it says above error..
Please anyone help in this, im wasting lot of time on this...
1) To avoid duplicate images, append time() in image name.
2) Remove $documents->save(false); before UploadInstance.
public function actionCreate() {
$model = new Projects();
$documents = new ProjectDocuments();
$borrower_id = Yii::$app->user->identity->id;
$code = $model->accessCode(10);
if ($model->load(Yii::$app->request->post())) {
//All $model related things will bw done
//In this im doing file upload
$documents->borrower_id = $borrower_id;
$documents->project_id = $code;
if(UploadedFile::getInstance($documents, 'sars_certificate')){
$image = UploadedFile::getInstance($documents, 'sars_certificate');
$imageName = time().$image->name;
$path = "user/purchase_order/".$imageName;
if($image->saveAs($path)){
$documents->sars_certificate = $imageName;
}
}
$documents->save(false);
return $this->redirect(['index']);
}
}
Update
public function actionCreate() {
$model = new Projects();
$documents = new ProjectDocuments();
$borrower_id = Yii::$app->user->identity->id;
$code = $model->accessCode(10);
if ($model->load(Yii::$app->request->post())) {
//All $model related things will bw done
//In this im doing file upload
$documents->borrower_id = $borrower_id;
$documents->project_id = $code;
if(UploadedFile::getInstance($documents, 'sars_certificate')){
$image = UploadedFile::getInstance($documents, 'sars_certificate');
if($image){
$imageName = time().$image->name;
$path = "user/purchase_order/".$imageName;
if($image->saveAs($path)){
$documents->sars_certificate = $imageName;
}
}
}
$documents->save(false);
return $this->redirect(['index']);
}
}
A PHP Error was encountered
Severity: Notice Message:
Undefined index: uploadimg
Filename: models/upload_model.php
Line Number: 26
My code:
Controller
public function do_upload(){
$this->upload->do_upload();
if($this->upload_model->Doupload()){
echo 1;
}else{
echo 0;
}
}
private function set_config_option(){
$config =array(
'allowed_type' => 'gif|jpg|png|jpeg|pdf|doc|xml|zip|rar',
'file_size' => '100',
'max_width' => '1024',
'overwrite' => TRUE,
'max_height' => '768',
);
return $config;
}
Model
private function set_config_option(){
$config =array(
'allowed_type' => 'gif|jpg|png|jpeg|pdf|doc|xml|zip|rar',
'file_size' => '2048000',
'max_width' => '1024',
'overwrite' => TRUE,
'max_height' => '768'
);
return $config;
}
public function Doupload(){
$target_path = 'uploads/';
$target_file = $target_path. basename($_FILES['uploadimg']['name']);
$base_url = base_url();
$img_title = $this->input->post('imgname');
$this->upload->initialize('upload', $this->set_config_option());
// $img = $this->upload->do_upload();
}
Please help me...
The model isn't receiving the $_FILES object. Why you separate the upload proccess in 2 files (model & controller?, you store something in the database?). In the codeiniter documentation: https://ellislab.com/codeigniter/user-guide/libraries/file_uploading.html is all in the same file (controller).
Try following the example or try to add in the controller:
$this->upload_model->Doupload($_FILES);
and in the model:
public function Doupload($file){
$target_path = 'uploads/';
$target_file = $target_path. basename($file['uploadimg']['name']);
I guess you load the library with: $this->load->library('upload'); or by autoload config class. Hope it helps!
Add this to your ajax request and if that helps :)
And i assume you using form/multipart
xhr: function() {
var myXhr = $.ajaxSettings.xhr();
return myXhr;
},
Is there a way when uploading images (JPEG) to check the DPI?
I would like to integrate it into a form, so as a validator.
You have to open the image with Imagick (or Gmagick) and then call getImageResolution.
$image = new Imagick($path_to_image);
var_dump($image->getImageResolution());
result:
Array
(
[x]=>75
[y]=>75
)
Edit:
For an integration into symfony, you can use a custom validator for that. You extends the default one to validate a file and add the DPI restriction.
Create this one into /lib/validator/myCustomValidatorFile .class.php:
<?php
class myCustomValidatorFile extends sfValidatorFile
{
protected function configure($options = array(), $messages = array())
{
parent::configure($options, $messages);
$this->addOption('resolution_dpi');
$this->addMessage('resolution_dpi', 'DPI resolution is wrong, you should use image with %resolution_dpi% DPI.');
}
protected function doClean($value)
{
$validated_file = parent::doClean($value);
$image = new Imagick($validated_file->getTempName());
$resolution = $image->getImageResolution();
if (empty($resolution))
{
throw new sfValidatorError($this, 'invalid');
}
if ((isset($resolution['x']) && $resolution['x'] < $this->getOption('resolution_dpi')) || (isset($resolution['y']) && $resolution['y'] < $this->getOption('resolution_dpi')))
{
throw new sfValidatorError($this, 'resolution_dpi', array('resolution_dpi' => $this->getOption('resolution_dpi')));
}
return $validated_file;
}
}
Then, inside your form, use this validator for your file:
$this->validatorSchema['file'] = new myCustomValidatorFile(array(
'resolution_dpi' => 300,
'mime_types' => 'web_images',
'path' => sfConfig::get('sf_upload_dir'),
'required' => true
));
Can someone help with an example of how to use external files(css,Javascript and images) in Kohana 3.2.2
Here is what I did:
in /classes/controller/hello.php
<?php defined('SYSPATH') OR die('No Direct Script Access');
Class Controller_Hello extends Controller_Template
{
public $template = 'site'; // Default template
public function action_index()
{
$this->template->styles = array('media/css/style.css'=>'screen');
//$this->template->scripts = array('assets/js/jqtest.js');
}
public function before()
{
parent::before();
if($this->auto_render)
{
// Initialize empty values
$this->template->styles = array();
$this->template->scripts = array();
}
}
/**
* Fill in default values for our properties before rendering the output.
*/
public function after()
{
if($this->auto_render)
{
// Define defaults
$styles = array('media/css/style.css' => 'screen');
//$scripts = array(‘http://ajax.googleapis.com/ajax/libs/jquery/1.3.2.js');
// Add defaults to template variables.
$this->template->styles=array_reverse(array_merge
($this->template->styles,$styles));
//$this->template->scripts =array_reverse(array_merge
($this->template->scripts, $scripts));
}
// Run anything that needs to run after this.
parent::after();
}
}
And then in your view,you just need to use this
/application/views/site.php
<head>
<?php
foreach($styles as $file => $type)
{
echo HTML::style($file, array('media' => $type)), "";
}
?>
</head>
To add an image to your view
<li class="social"><?php echo html::image('media/images/phone.png');?>
Depends on if you want to run them through your controller or not. An example controller if you wanted to load media files using HMVC.
/classes/controller/media.php
class Controller_Media extends Controller {
protected $config = NULL;
public function before()
{
parent::before();
$this->config = Kohana::$config->load('media');
}
public function action_css()
{
$this->handle_request(
'style',
$this->request->param('path'),
$this->config['styles']['extension']
);
}
public function action_js()
{
$this->handle_request(
'script',
$this->request->param('path'),
$this->config['scripts']['extension']
);
}
public function action_img()
{
$image = $this->config['images']['directory'].$this->request->param('path');
$extension = $this->find_image_extension($image);
$this->handle_request(
'image',
$this->request->param('path'),
$extension
);
}
protected function handle_request($action, $path, $extension)
{
$config_key = Inflector::plural($action);
$file = $this->config[$config_key]['directory'].$path;
if ($this->find_file($file, $extension))
{
$this->serve_file($file, $extension);
}
else
{
$this->error();
}
}
protected function find_file($file, $extension)
{
$path_parts = pathinfo($file);
return Kohana::find_file('media', $path_parts['dirname']."/".$path_parts['filename'], $extension);
}
protected function find_image_extension($file)
{
foreach ($this->config['images']['extension'] as $extension)
{
if ($this->find_file($file, $extension) !== FALSE)
{
return $extension;
}
}
return FALSE;
}
protected function serve_file($file, $extension)
{
$path = $this->find_file($file, $extension);
$this->response->headers('Content-Type', File::mime_by_ext($extension));
$this->response->headers('Content-Length', (string) filesize($path));
$this->response->headers('Cache-Control','max-age=86400, public');
$this->response->headers('Expires', gmdate('D, d M Y H:i:s \G\M\T', time() + 86400));
$this->response->body(file_get_contents($path));
}
protected function error()
{
throw new HTTP_Exception_404('File :file not found.', array(
':file' => $this->request->param('path', NULL),
));
}
}
/config/media.php
return array(
'styles' => array(
'directory' => 'css/',
'extension' => 'css',
),
'scripts' => array(
'directory' => 'js/',
'extension' => 'js',
),
'images' => array(
'directory' => 'img/',
'extension' => array('png', 'jpg', 'jpeg', 'gif', 'ico', 'svg'),
),
);
routes.php
Route::set('media', 'media/<action>(/<path>)', array(
'path' => '.*?',
))
->defaults(array(
'controller' => 'media',
'action' => 'index',
));
Your default .htaccess should handle anything in your root directory without any additional code.
/webroot
--> application/
--> modules/
--> system
--> css/
--> scripts/
Anything called from http://domain.com/css will properly look in css/ because of the .htaccess rule to look for existing files/folder first and then load the index.php from Kohana.