Binary Upload

Have a programming question regarding your component, plug-in, extension or core hacks? Have an interesting tidbit, FAQ or programming tip you’d like to share? This is the place for you.

Moderators: tjay, seadap, Rogue4ngel, matthewhayashida

Post Reply
doctorD
Joomla! Apprentice
Joomla! Apprentice
Posts: 13
Joined: Sat Sep 01, 2007 8:31 pm

Binary Upload

Post by doctorD » Mon Sep 03, 2007 4:49 pm

I might be missing something here, but does anyone know how I use the JRequest to get binary data uplaoded through a form?

i.e. among other things the user is picking a file name and then this is being posted to the server.

Not much I'm doing seems to work, but it does update the record  ???

User avatar
jlleblanc
Joomla! Apprentice
Joomla! Apprentice
Posts: 30
Joined: Fri Aug 19, 2005 12:37 am
Location: Washington, DC / NoVA
Contact:

Re: Binary Upload

Post by jlleblanc » Mon Sep 03, 2007 5:21 pm

To handle file uploads, you want to use JFile after getting the variable through JRequest. Here's an example snippet from my iWebCal component:

Code: Select all

$file = JRequest::getVar( 'calendar', '', 'files', 'array' );
$filename = '';

if(isset($file) && is_array($file) && $file['name'] != '')
{
   $fullfilename = JPATH_SITE . DS . 'components' . DS . $option . DS . 'calendars' . DS . strtolower($file['name']);
   $filename = strtolower($file['name']);
   jimport('joomla.filesystem.file');
   
   if (JFile::exists($fullfilename)) {
      $mainframe->redirect("index.php?option=$option", "Upload failed, file already exists.");
      return;
   }

   if (!JFile::upload($file['tmp_name'], $fullfilename)) {
      $mainframe->redirect("index.php?option=$option", "Upload failed, check to make sure that /components/$option/calendars exists.");
      return;
   }
   
}
Joseph L. LeBlanc: http://www.jlleblanc.com
Frontend components start here: /components/com_[name]/[name].php
Backend components start here: /administrator/components/com_[name]/admin.[name].php

doctorD
Joomla! Apprentice
Joomla! Apprentice
Posts: 13
Joined: Sat Sep 01, 2007 8:31 pm

Re: Binary Upload

Post by doctorD » Mon Sep 03, 2007 5:35 pm

What about if I want to store the binary data in variable, addslash and then put this into a database.

I'm using:

Code: Select all

   
   if(isset($_POST['adminForm']) && $_FILES['hotbit_image']['size'] > 0)
   {
   $fileName = $_FILES['hotbit_image']['name'];
   $tmpName  = $_FILES['hotbit_image']['tmp_name'];
   $fileSize = $_FILES['hotbit_image']['size'];
   $fileType = $_FILES['hotbit_image']['type'];
   
   $fp      = fopen($tmpName, 'r');
   $content = fread($fp, filesize($tmpName));
   $content = addslashes($content);
   fclose($fp);

   $row->hotbit_image = $content;
   $row->hotbit_image_size = $filesize;
   $row->hotbit_image_type = $filetype;

   }

   if (!$row->store())
   {
      echo "<script> alert('".$row->getError()."');
      window.history.go(-1); </script>\n";
      exit();
   }


But it doesn't upload the binary data into mySQL.

I'm thinking the problem is with the whole store thing, and I should write my own SQL insert query.

I am new... reminder  ;D

doctorD
Joomla! Apprentice
Joomla! Apprentice
Posts: 13
Joined: Sat Sep 01, 2007 8:31 pm

Re: Binary Upload

Post by doctorD » Mon Sep 03, 2007 6:27 pm

Fixed :-)

fread was patently the wrong tool for the job, plus I had some variables wrong.

Fixed Code for interests sake:

Code: Select all

   
   $fileName = $_FILES['hotbit_image']['name'];
   $tmpName  = $_FILES['hotbit_image']['tmp_name'];
   $fileSize = $_FILES['hotbit_image']['size'];
   $fileType = $_FILES['hotbit_image']['type'];


   $content = file_get_contents($tmpName);
   $content = addslashes($content);

    //$fileName = addslashes($fileName);


:D :D :D :D :D :D

Pays not to do this whilst tired.

User avatar
matthewhayashida
Joomla! Enthusiast
Joomla! Enthusiast
Posts: 114
Joined: Sat Feb 10, 2007 8:26 pm
Location: Abbotsford, BC
Contact:

Re: Binary Upload

Post by matthewhayashida » Mon Sep 03, 2007 7:10 pm

MOD NOTE: Moving to Joombie Q/A
-Matt Hayashida

User avatar
CirTap
Joomla! Intern
Joomla! Intern
Posts: 73
Joined: Mon Dec 12, 2005 5:34 pm
Contact:

Re: Binary Upload

Post by CirTap » Mon Sep 03, 2007 11:14 pm

Hi,

just for the records...

The Framework equivalent of
  $_FILES['hotbit_image']
is
  JRequest::getVar( 'hotbit_image', '', 'files', 'array' );

another good example of how this is used can be found in the upload facility of the Media Manager
  /administrator/components/com_media/controllers/file.php -> MediaControllerFile::upload()

In this file you'll also see how the FTP layer is used to copy files in case PHP suffers from insufficent access rights.

Have fun,
CirTap
You can have programs written fast, well, and cheap, but you only get to pick 2 ...

"I love deadlines. I like the whooshing sound they make as they fly by." Douglas Adams

doctorD
Joomla! Apprentice
Joomla! Apprentice
Posts: 13
Joined: Sat Sep 01, 2007 8:31 pm

Re: Binary Upload

Post by doctorD » Mon Sep 03, 2007 11:22 pm

CirTap wrote:Hi,

just for the records...

The Framework equivalent of
  $_FILES['hotbit_image']
is
  JRequest::getVar( 'hotbit_image', '', 'files', 'array' );

another good example of how this is used can be found in the upload facility of the Media Manager
  /administrator/components/com_media/controllers/file.php -> MediaControllerFile::upload()

In this file you'll also see how the FTP layer is used to copy files in case PHP suffers from insufficent access rights.

Have fun,
CirTap



Hi thanks for the reply. I did look into this module and also read up on the framework, but the quickest solution was to use the one above.

For the file that displays the image, that was a bit trickier, not so much the 'how' in PHP, that was no problem, but finding a way to do it within Joomla. In the end I did what everyone else did and create a view.php, but to prevent any possible SQL injection I did a bit of mangling (mathematically) in both directions on the primary ID of the image file. This should prevent injection.

It would be nice to have a 100% internal Joomla solution, but it was sending the html header that stumped me here, easier just to do it the 'old' way.

User avatar
CirTap
Joomla! Intern
Joomla! Intern
Posts: 73
Joined: Mon Dec 12, 2005 5:34 pm
Contact:

Re: Binary Upload

Post by CirTap » Tue Sep 04, 2007 1:00 am

doctorD wrote:It would be nice to have a 100% internal Joomla solution, but it was sending the html header that stumped me here, easier just to do it the 'old' way.

do you use JDocumentHTML or JDocumentRAW ? The latter has a method called setMimeEncoding().
http://api.joomla.org/Joomla-Framework/ ... meEncoding

Just a thought.

Have fun,
CirTap
You can have programs written fast, well, and cheap, but you only get to pick 2 ...

"I love deadlines. I like the whooshing sound they make as they fly by." Douglas Adams

doctorD
Joomla! Apprentice
Joomla! Apprentice
Posts: 13
Joined: Sat Sep 01, 2007 8:31 pm

Re: Binary Upload

Post by doctorD » Tue Sep 04, 2007 1:21 am

CirTap wrote:
doctorD wrote:It would be nice to have a 100% internal Joomla solution, but it was sending the html header that stumped me here, easier just to do it the 'old' way.

do you use JDocumentHTML or JDocumentRAW ? The latter has a method called setMimeEncoding().
http://api.joomla.org/Joomla-Framework/ ... meEncoding

Just a thought.

Have fun,
CirTap



Interesting, but when pulling the data back out and putting into an img tag will it actually display an image? I'm not sure this would be the case. Might experiment with t.

User avatar
CirTap
Joomla! Intern
Joomla! Intern
Posts: 73
Joined: Mon Dec 12, 2005 5:34 pm
Contact:

Re: Binary Upload

Post by CirTap » Tue Sep 04, 2007 2:17 am

Hi,
not sure I understand what you're trying to do :)
So you get this uploaded file, it's stuffed into the database (BLOB presumably), and later you want to display the file (or in one go?)
As you can't put data into an tag (at least not cross-browser via the data: url schema) the src attribute of that would need to point to an URL that delivers a Content-type: image/blabla and all that stuff
Something like
 

Whatever that URL is, your Controller would have some"preview" task, create a JDocumentRAW for the "image layout", puts the binary data into the document's $buffer, and sends this "document".
In theory :)
There's no area in J! I know of where binaries are used in that way.

Intresting things you're doing, Dr.

Have fun,
CirTap
You can have programs written fast, well, and cheap, but you only get to pick 2 ...

"I love deadlines. I like the whooshing sound they make as they fly by." Douglas Adams

User avatar
jalil
Joomla! Enthusiast
Joomla! Enthusiast
Posts: 128
Joined: Wed Jul 04, 2007 4:54 am
Location: Kuala Lumpur, Malaysia
Contact:

Re: Binary Upload

Post by jalil » Tue Sep 11, 2007 3:43 am

there is this warning from PHP when using fread for binary files...two warnings but i think only one applies to your case.

Code: Select all

On systems which differentiate between binary and text files (i.e. Windows) the file must be opened 
with 'b' included in fopen() mode parameter.
 
<?php
$filename = "c:\\files\\somepic.gif";
$handle = fopen($filename, "rb");
$contents = fread($handle, filesize($filename));
fclose($handle);
?> 

Warning
When reading from anything that is not a regular local file, such as streams returned when reading remote files
or from popen() and fsockopen(), reading will stop after a packet is available.
This means that you should collect the data together in chunks as shown in the examples below.
 

<?php
// For PHP 5 and up
$handle = fopen("http://www.example.com/", "rb");
$contents = stream_get_contents($handle);
fclose($handle);
?> 





<?php
$handle = fopen("http://www.example.com/", "rb");
$contents = '';
while (!feof($handle)) {
  $contents .= fread($handle, 8192);
}
fclose($handle);
?> 



Note: If you just want to get the contents of a file into a string, use file_get_contents() as it has much better performance than the code above.


doctorD
Joomla! Apprentice
Joomla! Apprentice
Posts: 13
Joined: Sat Sep 01, 2007 8:31 pm

Re: Binary Upload

Post by doctorD » Tue Sep 11, 2007 5:07 am

jalil wrote:Note: If you just want to get the contents of a file into a string, use file_get_contents() as it has much better performance than the code above.


Yep that's what I did in the end, worked exceptionally well.

User avatar
jalil
Joomla! Enthusiast
Joomla! Enthusiast
Posts: 128
Joined: Wed Jul 04, 2007 4:54 am
Location: Kuala Lumpur, Malaysia
Contact:

Re: Binary Upload

Post by jalil » Tue Sep 11, 2007 5:18 am

doctorD wrote:
jalil wrote:Note: If you just want to get the contents of a file into a string, use file_get_contents() as it has much better performance than the code above.


Yep that's what I did in the end, worked exceptionally well.

YAHOO !!!  :pop

User avatar
ianmac
Joomla! Enthusiast
Joomla! Enthusiast
Posts: 237
Joined: Sat Sep 24, 2005 11:01 pm
Location: Toronto, Canada

Re: Binary Upload

Post by ianmac » Tue Sep 11, 2007 12:43 pm

CirTap wrote:Hi,
not sure I understand what you're trying to do :)
So you get this uploaded file, it's stuffed into the database (BLOB presumably), and later you want to display the file (or in one go?)
As you can't put data into an tag (at least not cross-browser via the data: url schema) the src attribute of that would need to point to an URL that delivers a Content-type: image/blabla and all that stuff
Something like
 

Whatever that URL is, your Controller would have some"preview" task, create a JDocumentRAW for the "image layout", puts the binary data into the document's $buffer, and sends this "document".
In theory :)
There's no area in J! I know of where binaries are used in that way.

Intresting things you're doing, Dr.

Have fun,
CirTap


You can also just add format=raw onto the query string, so you get:


The raw document type doesn't render any of the modules, etc etc - only your component, and none of the extra HTML stuff.

So in your views directory, create a folder called preview, and in that folder created a file called view.raw.php.

This view should handle the raw output.

Ian
Help test my Component XML Generator Tool!
http://extensions.joomla.org/component/option,com_mtree/task,viewlink/link_id,1997/Itemid,35/
All feedback appreciated!

User avatar
CirTap
Joomla! Intern
Joomla! Intern
Posts: 73
Joined: Mon Dec 12, 2005 5:34 pm
Contact:

Re: Binary Upload

Post by CirTap » Thu Sep 13, 2007 9:16 am

ianmac wrote:You can also just add format=raw onto the query string, so you get:


Is this also true for any custom component, or is it just an implied "feature" of the core components, esp. com_content?
I thought it's up to the controller to decide what URL params to resolve, and if there's a custom controller..?
but maybe I missed "some magic" going on behind the scenes

CirTap
You can have programs written fast, well, and cheap, but you only get to pick 2 ...

"I love deadlines. I like the whooshing sound they make as they fly by." Douglas Adams

User avatar
ianmac
Joomla! Enthusiast
Joomla! Enthusiast
Posts: 237
Joined: Sat Sep 24, 2005 11:01 pm
Location: Toronto, Canada

Re: Binary Upload

Post by ianmac » Thu Sep 13, 2007 12:11 pm

I *thought* that was just the way that the framework worked, but I could be wrong.  I'll have to do some experimentation.

Ian
Help test my Component XML Generator Tool!
http://extensions.joomla.org/component/option,com_mtree/task,viewlink/link_id,1997/Itemid,35/
All feedback appreciated!

User avatar
ianmac
Joomla! Enthusiast
Joomla! Enthusiast
Posts: 237
Joined: Sat Sep 24, 2005 11:01 pm
Location: Toronto, Canada

Re: Binary Upload

Post by ianmac » Thu Sep 13, 2007 3:24 pm

To follow up, here is the code from _createDocument in the JFactory class:

Code: Select all

   function &_createDocument()

   {

      jimport('joomla.document.document');

      jimport('joomla.environment.request');



      $lang   =& JFactory::getLanguage();



      //Keep backwards compatibility with Joomla! 1.0

      $raw   = JRequest::getBool('no_html');

      $type   = JRequest::getWord('format', $raw ? 'raw' : 'html');



      $attributes = array (

         'charset'   => 'utf-8',

         'lineend'   => 'unix',

         'tab'      => '  ',

         'language'   => $lang->getTag(),

         'direction'   => $lang->isRTL() ? 'rtl' : 'ltr'

      );



      $doc =& JDocument::getInstance($type, $attributes);

      return $doc;

   }


and then:

Code: Select all

   function display($cachable=false)

   {

      $document =& JFactory::getDocument();



      $viewType   = $document->getType();

      $viewName   = JRequest::getCmd( 'view', $this->_name );

      $viewLayout   = JRequest::getCmd( 'layout', 'default' );



      $view = & $this->getView( $viewName, $viewType);



      // Get/Create the model

      if ($model = & $this->getModel($viewName)) {

         // Push the model into the view (as default)

         $view->setModel($model, true);

      }



      // Set the layout

      $view->setLayout($viewLayout);



      // Display the view

      if ($cachable) {

         global $option;

         $cache =& JFactory::getCache($option, 'view');

         $cache->get($view, 'display');

      } else {

         $view->display();

      }

   }


So basically, yes, this will work with any custom component.  On a side note, core components are receiving fewer and fewer special privileges, with a view to separating framework from application more.  This makes it easier to replace certain functionality with other custom functionality.

Ian
Help test my Component XML Generator Tool!
http://extensions.joomla.org/component/option,com_mtree/task,viewlink/link_id,1997/Itemid,35/
All feedback appreciated!

alc97
Joomla! Fledgling
Joomla! Fledgling
Posts: 2
Joined: Mon Dec 24, 2007 1:27 am

Re: Binary Upload

Post by alc97 » Fri Jan 11, 2008 11:58 am

hi,
I'm having trouble to view binary data after I saved it.
My image tag looks like this:


c is the controllername.
In my views directory, i have e1 folder with view.raw.php and a template folder for image.php file
Inside view.raw.php, i have this function:

Code: Select all

   function _displayImage($tpl)
   {
      global $mainframe;
      //code for checking user

      $e1 =& $this->get('data');
      $this->assignRef('filesize', $e1->filesize);
      $this->assignRef('filetype', $e1->filetype);
      $this->assignRef('flogo', $e1->flogo);

      parent::display($tpl);
   }


And inside image.php

Code: Select all

<?php
defined('_JEXEC') or die('Restricted Access.');

header("Content-Length: $this->filesize");
header("Content-Type: $this->filetype");
header("Content-Description: PHP Generated Data");
echo $this->flogo;
?>


But I can not see the image.
If I typed in the link directly to browser address, it shows all the binary data as a text. And page content-type is text/html  ???

doctorD
Joomla! Apprentice
Joomla! Apprentice
Posts: 13
Joined: Sat Sep 01, 2007 8:31 pm

Re: Binary Upload

Post by doctorD » Fri Jan 11, 2008 12:34 pm

PHP mistake

header("Content-Type: $this->filetype");

should be

header("Content-Type: " . $this->filetype);

8)

alc97
Joomla! Fledgling
Joomla! Fledgling
Posts: 2
Joined: Mon Dec 24, 2007 1:27 am

Re: Binary Upload

Post by alc97 » Sat Jan 12, 2008 9:14 am

Thanks for the reply.
I changed the code in image.php to header("Content-Type: " . $this->filetype), but still won't show up.
There's a mistake when saving the image, so I have to comment out the "addslashes" line. Now I can see the image.
May be the reason is I use JTable object, not direct sql command.

Code: Select all

   function getLogoFile($userfile)
   {
      jimport('joomla.filesystem.file');
      $logo = JFile::read($userfile['tmp_name']);
      //$logo = file_get_contents($userfile['tmp_name']);
      
      //**********
      //$logo = addslashes($logo);
      //**********

      return $logo;
   }


Post Reply