Codeigniter - two upload fields in one form - codeigniter

I'm trying to upload an image and an mp3 in Codeigniter, from a form with two file input fields. The image field is called userfile, the mp3 field is called trackfile.
In my model I have this code (modified):
$image_resource = $this->library_model->upload_image($_FILES);
$data = array(
'name' => $this->input->post('name'),
'imageresource' => $image_resource
);
$this->db->insert('table_name',$data);
$insert_id = $this->db->insert_id();
if ($_FILES && $_FILES['trackfile']['name'] !== "") {
$config = array(
'allowed_types' => 'mp3',
'upload_path' => './assets/samples/'
);
$this->load->library('upload',$config);
//echo 'about to upload';
if ($this->upload->do_upload('trackfile')) {
$file_data = $this->upload->data();
//echo 'uploaded: <pre>'; print_r($file_data); echo '</pre>'; die();
$track_data['trackfile'] = $file_data['file_name'];
$this->db->where('id', $insert_id);
return $this->db->update('table_name',$track_data);
} else {
echo 'Failed: ';
echo $this->upload->display_errors();
echo 'FILE DATA: <pre>'; print_r($_FILES['trackfile']); echo '</pre>';
}
}
My problem is that this produces the error "The filetype you are attempting to upload is not allowed." I've checked the mp3 type, it's audio/mpeg, which is in the mimes.php file.
This only happens when I'm also uploading an image. If I leave the image field blank, the mp3 uploads fine. Any help much appreciated.

EDIT
According to the CI docs, the allowed_types portion of the config is a pipe delimited list of mime types, not file extensions. For example, mp3 have the mime type 'audio/mpeg'. So your allowed_types config should look like this:
$config = array(
'allowed_types' => 'audo/mpeg|audio/x-wav|audio/x-aiff|application/ogg',
'upload_path' => './assets/samples/'
);
If that doesn't work try to initialize the library as mentioned here.

Related

Function wp_generate_attachment_metadata returns always empty array in ajax function

I have searched far and wide, but have not found a solution.
I have a real estate ad insertion form, I need to be able to upload photos of the listings. I can upload the photos to the server via ajax, return the filenames in a textarea and always via ajax, after submitting the form, I can upload the photos to wordpress and attach them to the ad
The only problem is that it does not generate the photo metadata, wp_generate_attachment_metadata always returns an empty array.
I can't find a solution about it. I have another plugin with a similar form, but there I post the form not via ajax, but with the action = "post", and I can safely generate the metadata.
This is the code with which I insert the attachments and link them to the newly created post.
Hope someone can help me
//$filename = domoria-torino-strada-della-fornace-druento-15.jpg
if ($filename != '') {
$wp_upload_dir = wp_upload_dir();
$filename_path = $wp_upload_dir['path'] .'/'. $filename;
$filename_url = $wp_upload_dir['url'] .'/'. $filename;
$guid = $wp_upload_dir['url'] . '/' . basename( $filename_path );
$attachment = array(
'guid'=> $guid,
'post_mime_type' => 'image/jpeg',
'post_title' => $filename,
'post_content' => '',
'post_status' => 'inherit',
'post_parent' => $post_id
);
$attach_id = wp_insert_attachment( $attachment, $filename_path);
if($iter === 0){
set_post_thumbnail( $post_id, $attach_id );
}
$ids [] = $attach_id; //this array needs for an ACF field
//filename_path = home/uxo80ef6/domains/homeprime.sviluppo.host/public_html/wp-content/uploads/2021/12/domoria-torino-strada-della-fornace-druento-15.jpg
//$attach_id = 629
$file_uploaded_path = get_attached_file($attach_id);
require_once( ABSPATH . 'wp-admin/includes/image.php' );
require_once( ABSPATH . 'wp-admin/includes/file.php' );
require_once( ABSPATH . 'wp-admin/includes/media.php' );
$attach_data = wp_generate_attachment_metadata( $attach_id, $file_uploaded_path );
wp_update_attachment_metadata( $attach_id, $attach_data );
$iter++;
}
UPDATE: The problem is due to getimagesize called by wp_generate_attachment_metadata that can't find the file by file_path, however the file is on the server.
I rewrote some parts of the code you posted:
change hardcoded post_mime_type with wp_check_filetype() instead.
rename some of the variables to: $file_name, $file_path, $parent_post_id
removed unused $filename_url
added $parent_post_id as the third argument into wp_insert_attachment()
removed get_attached_file() function and used $file_path for wp_generate_attachment_metadata()
<?php
// $file_name = domoria-torino-strada-della-fornace-druento-15.jpg
if (!empty($file_name)) {
// The ID of the post this attachment is for.
// eg. $parent_post_id = 37;
// Get the path to the upload directory.
$wp_upload_dir = wp_upload_dir();
$file_path = $wp_upload_dir['path'] . '/' . $file_name;
// Check the type of file. We'll use this as the 'post_mime_type'.
$filetype = wp_check_filetype(basename($file_path), null);
// Prepare an array of post data for the attachment.
$attachment = array(
'guid' => $wp_upload_dir['url'] . '/' . basename($file_path),
'post_mime_type' => $filetype['type'],
'post_title' => sanitize_title($file_name),
'post_content' => '',
'post_status' => 'inherit'
);
// Insert the attachment.
$attach_id = wp_insert_attachment($attachment, $file_path, $parent_post_id);
// Set the first attachment as Featured image.
if ($iter === 0) {
set_post_thumbnail($parent_post_id, $attach_id);
}
// ACF field array data.
$ids[] = $attach_id;
// Make sure that this file is included, as wp_generate_attachment_metadata() depends on it.
require_once(ABSPATH . 'wp-admin/includes/image.php');
// Generate the metadata for the attachment, and update the database record.
$attach_data = wp_generate_attachment_metadata($attach_id, $file_path);
wp_update_attachment_metadata($attach_id, $attach_data);
$iter++;
}

How can i change the image upload directory and view image url in laravel

In my script all images uploaded goes into directory "ib" but i want to change that directory to a different name eg. "imgib"
here is what i did so far. i changed the code vlues from "ib" to "imgib"
} else {
// upload path
$path = 'imgib/';
// if path not exists create it
if (!File::exists($path)) {
File::isDirectory($path) or File::makeDirectory($path, 0777, true, true);
}
// move image to path
$upload = $request->file('uploads')->move($path, $imageName);
// file name
$filename = url($path) . '/' . $imageName;
// method server host
$method = 1;
}
// if image uploded
if ($upload) {
// if user auth get user id
if (Auth::user()) {$userID = Auth::user()->id;} else { $userID = null;}
// create new image data
$data = Image::create([
'user_id' => $userID,
'image_id' => $string,
'image_path' => $filename,
'image_size' => $fileSize,
'method' => $method,
]);
// if image data created
if ($data) {
// success array
$response = array(
'type' => 'success',
'msg' => 'success',
'data' => array('id' => $string),
);
// success response
return response()->json($response);
} else {
if (file_exists('imgib/' . $filename)) {$delete = File::delete('imgib/' . $filename);}
// error response
return response()->json(array(
'type' => 'error',
'errors' => 'Opps !! Error please refresh page and try again.',
));
}
so far everything looks ok and it creates "imgib" directory automatically and all uploads go into "imgib" directory.
But the issue is, image url still uses the same old directory name.
eg. site.org/ib/78huOP09vv
How to make it get the correct url eg. site.org/imgib/78huOP09vv
Thanks for the help everyone. I managed to fix the issue by editing viewimage.blade.php
Yes of course need to clear the browser cache after editing the files.

Drupal 8, add an image field from a BuildForm with preview

I created a custom form from a buildForm function. In this form, I would like add an image field.
I can do that via this code :
$form['main']['image'] = array(
'#type' => 'text_format',
'#title' => t('image'),
'#default_value' => array(10),
);
I can upload and remove the image from my form. However, when I upload an image, I haven't this preview.
I mean, when I create a content via the Drupal UI. I can add a preconfigured "image" field. When I upload an image via this "image" field, I have a preview of the image.
And here, when I create the field element programmatically, I haven't a preview of the image when I upload her.
How use api Drupal for have the preview of the image when I upload her via my "image" field ?
So here is how I got my form to display the thumbnail image. What I basically did was take the code in ImageWidget::process, put it in a theme preprocessor and set the #theme property of the element to image_widget.
Your image element in your form class should look like this:
$form['profile_image'] = [
'#type' => 'managed_file',
'#title' => t('Profile Picture'),
'#upload_validators' => array(
'file_validate_extensions' => array('gif png jpg jpeg'),
'file_validate_size' => array(25600000),
),
**'#theme' => 'image_widget',**
**'#preview_image_style' => 'medium',**
'#upload_location' => 'public://profile-pictures',
'#required' => TRUE,
];
In your name_of_default_theme.theme file, you need the following:
function name_of_default_theme_preprocess_image_widget(&$variables) {
$element = $variables['element'];
$variables['attributes'] = array('class' => array('image-widget', 'js-form-managed-file', 'form-managed-file', 'clearfix'));
if (!empty($element['fids']['#value'])) {
$file = reset($element['#files']);
$element['file_' . $file->id()]['filename']['#suffix'] = ' <span class="file-size">(' . format_size($file->getSize()) . ')</span> ';
$file_variables = array(
'style_name' => $element['#preview_image_style'],
'uri' => $file->getFileUri(),
);
// Determine image dimensions.
if (isset($element['#value']['width']) && isset($element['#value']['height'])) {
$file_variables['width'] = $element['#value']['width'];
$file_variables['height'] = $element['#value']['height'];
} else {
$image = \Drupal::service('image.factory')->get($file->getFileUri());
if ($image->isValid()) {
$file_variables['width'] = $image->getWidth();
$file_variables['height'] = $image->getHeight();
}
else {
$file_variables['width'] = $file_variables['height'] = NULL;
}
}
$element['preview'] = array(
'#weight' => -10,
'#theme' => 'image_style',
'#width' => $file_variables['width'],
'#height' => $file_variables['height'],
'#style_name' => $file_variables['style_name'],
'#uri' => $file_variables['uri'],
);
// Store the dimensions in the form so the file doesn't have to be
// accessed again. This is important for remote files.
$element['width'] = array(
'#type' => 'hidden',
'#value' => $file_variables['width'],
);
$element['height'] = array(
'#type' => 'hidden',
'#value' => $file_variables['height'],
);
}
$variables['data'] = array();
foreach (Element::children($element) as $child) {
$variables['data'][$child] = $element[$child];
}
}
The solution works well, but the image module is missing a class with the #FormElement annotation. That is why the element isn't rendered properly.
Can you try with managed_file type?
'#type' => 'managed_file'
First some clarifications, then some observations and then the code that worked for me.
Clarifications:
I am using Drupal 9, but the solution proposed below may work also
for Drupal 8.
By "default temporary directory" I mean the directory defined in the following settings
file
[DrupalrootDirectory]/sites/default/settings.php
using
$settings['file_temp_path'] = '/The/Absolute/Path/To/Your/Temporary/Directory';
or defined by your operating system and that you can check in the Drupal administration
menu:
[YourSiteWebAddress]/admin/config/media/file-system
When something is written inside square brackets [], like this, [DrupalrootDirectory], it means that you should replace it with the actual name in your system, Drupal installation or custom module/file, without the square brackets.
Observations:
No need to create apriory any directories inside the default
temporary directory. They will be created automatically.
When you click the Remove button (which appears automatically as soon you upload a file in your custom form), the image file and the thumbnail files are deleted from the default temporary directory.
It does not matter if you define your default temporary directory inside the default site location,
e.g.,
[DrupalrootDirectory]/sites/default/files
or outside it, for example,
[DrupalrootDirectory]/sites/other/files
In my case, I defined it to:
[DrupalrootDirectory]/sites/default/files/temp
No need to make changes to .htaccess (in Apache server) file inside the default temporary directory or
inside
[DrupalrootDirectory]/sites/default/files
Keep them as Drupal created them.
No need to change file rights to "777" inside the default temporary directory, "775" is enough.
Check that your Drupal installation is actually creating thumbnails for images uploaded using the
administration menu:
[YourSiteWebAddress]/admin/content/media
when using the "Add media" link
[YourSiteWebAddress]/media/add/image
No need to make any other changes inside Drupal settings
file
[DrupalrootDirectory]/sites/default/settings.php
The code that worked for me:
It is based in the code published above by "Je Suis Alrick". But his code was not working for me, neither I could not find in which part of his code the thumbnail image was actually created. In my search for it, this post helped
Generate programmatically image styles with Drupal 8
So, here is the final code:
In your custom module, in the custom form file, most probably located
in:
[DrupalrootDirectory]/modules/custom/[NameOfYourCustomModule]/src/Form/[NameOfYourCustomForm].php
you add the element to be used to upload the image file:
$form['profile_image'] = [
'#type' => 'managed_file',
'#title' => t('Profile Picture'),
'#upload_validators' => array(
'file_validate_extensions' => array('gif png jpg jpeg'),
'file_validate_size' => array(25600000),
),
'#theme' => 'image_widget',
'#preview_image_style' => 'medium',
'#required' => TRUE,
];
So far, the same as in the code of "Je Suis Alrick", except that I deleted the definition for '#upload_location', so the default temporary directory will be used avoiding security complaints.
The important part here is:
the definition of the '#theme', which may be any name, but in this case is 'image_widget';
and the definition of '#preview_image_style', which must be the machine name of one of the image styles defined in your Drupal installation, that you can check in your administration
menu
[YourSiteWebAddress]/admin/config/media/image-styles
For this case the style 'medium' will be used, which is one of the image styles created by default by Drupal.
Then, in the module file of your custom module, named [NameOfYourCustomModule].module and most probably located
in:
[DrupalrootDirectory]/modules/custom/[NameOfYourCustomModule]/
You will need to paste the following code:
<?php
use Drupal\image\Entity\ImageStyle;
function [NameOfYourCustomModule]_preprocess_image_widget(&$variables) {
$element = $variables['element'];
$variables['attributes'] = array('class' => array('image-widget', 'js-form-managed-file', 'form-managed-file', 'clearfix'));
if (!empty($element['fids']['#value'])) {
$file = reset($element['#files']);
$element['file_' . $file->id()]['filename']['#suffix'] = ' <span class="file-size">(' . format_size($file->getSize()) . ')</span> ';
$file_variables = array(
'style_name' => $element['#preview_image_style'],
'uri' => $file->getFileUri(),
);
// Determine image dimensions.
if (isset($element['width']['#value']) && isset($element['height']['#value'])) {
$file_variables['width'] = $element['width']['#value'];
$file_variables['height'] = $element['height']['#value'];
} else {
$image = \Drupal::service('image.factory')->get($file->getFileUri());
if ($image->isValid()) {
$file_variables['width'] = $image->getWidth();
$file_variables['height'] = $image->getHeight();
$style = ImageStyle::load($file_variables['style_name']);
$image_uri = $file->getFileUri();
$destination = $style->buildUri($image_uri);
$style->createDerivative($image_uri, $destination);
}
else {
$file_variables['width'] = $file_variables['height'] = NULL;
}
}
$element['preview'] = array(
'#weight' => -10,
'#theme' => 'image_style',
'#width' => $file_variables['width'],
'#height' => $file_variables['height'],
'#style_name' => $file_variables['style_name'],
'#uri' => $file_variables['uri'],
);
// Store the dimensions in the form so the file doesn't have to be
// accessed again. This is important for remote files.
$element['width'] = array(
'#type' => 'hidden',
'#value' => $file_variables['width'],
);
$element['height'] = array(
'#type' => 'hidden',
'#value' => $file_variables['height'],
);
}
$variables['data'] = array();
foreach (\Drupal\Core\Render\Element::children($element) as $child) {
$variables['data'][$child] = $element[$child];
}
}
You should note that at the end of the name of the function, the name of the theme 'image_widget' is included, which tells Drupal to process your form element using the defined above function: [NameOfYourCustomModule]_preprocess_image_widget
What have I added?
The line at the
top:
use Drupal\image\Entity\ImageStyle;
And the following four lines that actually create the image thumbnail inside the default temporary directory:
$style = ImageStyle::load($file_variables['style_name']);
$image_uri = $file->getFileUri();
$destination = $style->buildUri($image_uri);
$style->createDerivative($image_uri, $destination);
With the addition of these five lines I got it working!
Nice answer thx, only change I'd make is using Token for upload location, and Bytes for file upload size, although I guess it depends on the use case. Something like the below (stripped out most of the code for the sake of simplicity.
namespace Drupal\my_module\Form;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\Component\Utility\Bytes;
use Drupal\Core\Utility\Token;
class SampleForm extends FormBase
{
protected $currentUser;
protected $token;
public function __construct(AccountProxyInterface $current_user, Token $token) {
$this->currentUser = $current_user;
$this->token = $token;
}
public static function create(ContainerInterface $container)
{
return new static(
$container->get('current_user'),
$container->get('token')
);
}
/**
* {#inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$form['sample_image'] = [
'#type' => 'managed_file',
'#title' => t('Profile Picture'),
'#upload_validators' => array(
'file_validate_extensions' => array('gif png jpg jpeg'),
'file_validate_size' => file_upload_max_size() / pow(Bytes::KILOBYTE, 2) . 'M',
),
'#theme' => 'image_widget',
'#preview_image_style' => 'medium',
'#upload_location' => $this->token->replace('private://[date:custom:Y]-[date:custom:m]'),
'#required' => TRUE,
];
return $form;
}
}
Theme it to work on multiple file upload. From #Je Suis Alrick answer above.
function themename_preprocess_image_widget(&$variables) {
$element = $variables['element'];
$variables['attributes'] = array('class' => array('image-widget', 'js-form-managed-file', 'form-managed-file', 'clearfix'));
if (!empty($element['fids']['#value'])) {
foreach ($element['#files'] as $file) {
$element['file_' . $file->id()]['filename']['#suffix'] = ' <span class="file-size">(' . format_size($file->getSize()) . ')</span> ';
$file_variables = array(
'style_name' => $element['#preview_image_style'],
'uri' => $file->getFileUri(),
);
// Determine image dimensions.
if (isset($element['#value']['width']) && isset($element['#value']['height'])) {
$file_variables['width'] = $element['#value']['width'];
$file_variables['height'] = $element['#value']['height'];
} else {
$image = \Drupal::service('image.factory')->get($file->getFileUri());
if ($image->isValid()) {
$file_variables['width'] = $image->getWidth();
$file_variables['height'] = $image->getHeight();
}
else {
$file_variables['width'] = $file_variables['height'] = NULL;
}
}
$element['preview'][] = array(
'#weight' => -10,
'#theme' => 'image_style',
'#width' => $file_variables['width'],
'#height' => $file_variables['height'],
'#style_name' => $file_variables['style_name'],
'#uri' => $file_variables['uri'],
);
// Store the dimensions in the form so the file doesn't have to be
// accessed again. This is important for remote files.
$element['width'] = array(
'#type' => 'hidden',
'#value' => $file_variables['width'],
);
$element['height'] = array(
'#type' => 'hidden',
'#value' => $file_variables['height'],
);
}
}
$variables['data'] = array();
foreach (\Drupal\Core\Render\Element::children($element) as $child) {
$variables['data'][$child] = $element[$child];
}
}

Uploading an image with Code Igniter?

I'm trying to set a site up so I can upload images using a web form in Code Igniter(CI). I'm not getting any errors but the file is not being saved either. I wanted to know if those that were successful in uploading images could help explain what might be the issue?
View:
<?php
echo form_open_multipart('admin/galleryUpload') . "\n";
echo "<div class='span-8'><span class='text'>Image:</span>" . form_upload('uploadImg') . "</div>";
foreach ($gallery as $picture)
{
$order[] = $picture->order;
}
$order[] = count($order) + 1;
echo "<div class='span-6 last'><span>Image Order #:</span>" . form_dropdown('order', $order) . "</div><div class='span-14'> </div>";
$conf = array('name' => 'alt_text', 'size' => '75');
echo "<div class='span-14 last'><span>Discription:</span>" . form_input($conf) . "<br /></div>";
echo form_hidden('propertyID', "$propertyID");
echo form_submit('upload', 'Upload');
echo form_close();
?>
Controller:
class Admin extends Controller
{
function galleryUpload()
{
if (! $this->session->userdata('is_admin'))
{
redirect('admin/index');
}
else
{
$this->load->model('admin_model');
$this->admin_model->imgUpload();
}
}
}
Model:
class Admin_model extends Model
{
function imgUpload()
{
$id = $this->input->post('propertyID');
$order = $this->input->post('order');
$alt_text = $this->input->post('alt_text');
$config = array(
'allowed_types' => 'jpg|jpeg|gif|png',
//'upload_path' => '../' . $this->imgPath($id),
'upload_path' => '../img/galleries/temp/',
'max_size' => '5000', // 5MB files max
);
$this->load->library('upload', $config);
$this->upload->do_upload();
$image_data = $this->upload->data();
$config = array(
'source_image' => $image_data['full_path'],
'new_image' => $this->imgPath($id) . '/thumbs',
'maintain_ratio' => TRUE,
'width' => '60'
);
$this->load->library('image_lib', $config);
$this->image_lib->resize();
}
}
From the user guide:
By default the upload routine expects the file to come from a form
field called userfile, and the form must be a multipart type
So you either have to change the name of the form field to userfile:
form_upload('userfile')
or pass the name of your form field to do_upload:
$this->upload->do_upload('uploadImg');

image uploading with codeigniter

Am trying to upload an image and save the images full path in my images table but i dont know how to get the full path it out of the $this->upload->data() array this is my code below.
//assigns the user's sessioned id to the variable $user_id
$user_id = $this->session->userdata('user_id');
//sets rules for the image that is being uploaded
$config['overwrite'] = FALSE; //does not overwrite any image adds +1 instead
$config['encrypt_name'] = FALSE; //encrypts the images name
$config['remove_spaces'] = TRUE; //removes spaces from the images name
$config['file_name'] = $user_id."_0.jpg";/*gives the image a new name combination of the user's id and a number*/
$config['upload_path'] = './uploads'; // the uploaded images path
$config['allowed_types'] = 'jpg|png';/*types of image extentions allowed to be uploaded*/
$config['max_size'] = '2048';// maximum file size that can be uploaded (2MB)
if ( ! is_dir($config['upload_path']) ) /* this checks to see if the file path is wrong or does not exist.*/
die("THE UPLOAD DIRECTORY DOES NOT EXIST"); // error for invalid file path
$this->load->library('upload',$config); /* this loads codeigniters file upload library*/
//this checks for errors incase the image upload breaks a set rule.
if (! $this->upload->do_upload() ) {
echo "UPLOAD ERROR ! ".$this->upload->display_errors(); //image error
}
else {
// success message to show that the image was successfuly uploaded.
echo "THE IMAGE HAS BEEN UPLOADED : "; var_dump($this->upload->data() );
}
All I needed to do was to store the array $this->upload->data(); in a variable for example
$image_info = $this->upload->data();
and from the $image_info variable I can access the images properties like so.
$image_info['full_path'];
$image_info['file_name'];
You should be seeing in the dump for $this->upload->data() the following array:
Array
(
[file_name] => mypic.jpg
[file_type] => image/jpeg
[file_path] => /path/to/your/upload/
[full_path] => /path/to/your/upload/jpg.jpg
[raw_name] => mypic
[orig_name] => mypic.jpg
[client_name] => mypic.jpg
[file_ext] => .jpg
[file_size] => 22.2
[is_image] => 1
[image_width] => 800
[image_height] => 600
[image_type] => jpeg
[image_size_str] => width="800" height="200"
)
So you can simply use something like:
if ($uploaded_image = $this->upload->do_upload() ){
// success message to show that the image was successfuly uploaded.
echo "THE IMAGE HAS BEEN UPLOADED : ";
$full_path = $uploaded_image['full_path'];
} else {
echo "UPLOAD ERROR ! ".$this->upload->display_errors();//image error
}

Resources