
Bambi Twins
Bambi-Editor comes in two build flavors: Desktop and Web Start. If you're a regular user that wants to have fun with images, save them to a computer and maybe print them, you want to download and install the desktop edition. If you're a website owner or developer that wants to give end end users ability to upload images specifically cropped and/or scaled to your requirements, you want Java Web Start edition. Upon each release, Bambi dev team distributes both editions simultaneously. They're both released to Sourceforge. Desktop is available for a traditional download, Web Start is available as a live JAR that can be linked to via JNLP. Feature-wise they are identical, but they are configured differently.1 2 3 | # codebase /bambi-editor # compiles and builds desktop distribution mvn clean package -P app |
1 2 3 | # codebase /bambi-editor # compiles and builds web start distribution mvn clean package -P ws |
1 2 3 | # codebase /bambi-webstart # compiles webstart JAR and config JAR mvn clean package -Djnlp.host=bambieditor.sourceforge.net -Dupload. dir = |
So You're a Web Developer?
To run Bambi-Editor as JWS on your website you need to provide a JNLP (Java Network Launching Protocol) script. In that script you will reference your own configuration JAR, which must include configuration file and (optionally) any custom plugins you may have written.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <? xml version = "1.0" encoding = "UTF-8" ?> < information > < title >Bambi Editor</ title > < vendor >mrazjava</ vendor > </ information > < resources > < property name = "jnlp.packEnabled" value = "false" /> <!-- <property name="jnlp.bambieditor.splash-title" value="<html><h1>Custom Title</h1></html>" /> --> <!-- Application Resources --> < j2se version = "1.7+" href = "http://java.sun.com/products/autodl/j2se" initial-heap-size = "128m" max-heap-size = "1024m" /> < jar href = "bambi-config-0.9.1.jar" download = "lazy" /> </ resources > < application-desc main-class = "org.zimowski.bambi.editor.BambiApp" progress-class = "org.zimowski.bambi.webstart.WebStartProgress" /> < update check = "always" policy = "always" /> </ jnlp > |
An example of custom configured BambiEditor running of a different domain can be seen on my personal server. There you can launch bambi with custom configuration but core (extension) still pointing to our sourceforge base.
Of course, if you want you can download source code and build entire thing yourself without linking to our JAR. We assume, that if you're that adventurous you know what you're doing.
Singing the Bambi Song
When user uploads a photo from Bambi-Editor, server processing script needs to sing to the same tune that Bambi does. It is not required to use any particular technology, it just needs to comply with Bambi's upload plugin protocol. Bambi-Editor ships with two upload plugins out of the box, which should cover most needs: They both get end-user's image to your server, though the form post plugin is by far the more flexible of the two. FTP plugin does not require a server side script, form post does. It is the form post plugin ability to communicate with a script that makes it so powerful and versatile. In this article we focus on explaining how to accept Bambi image upload via form post with PHP server script saving a photo to MySQL blob.In general, the form-post data flow scheme is as following:
FTP upload scheme is similar, except there is no script, so image is always saved to server's filesystem.So the scenario is this: Your end users play with their image applying various Bambi filters, then when ready upload it over internet targetting a URL you configured. Bambi handles all the latency issues so your user sees a real-time progress on the UI. Your processing script (URL) is essentially free to do anything it wants with the image. Typically a script will save the image, either to a local filesystem or a database blob, but there is nothing precluding it from doing other things like sending it via e-mail or posting to a twitter account. Possibilities are endless. Here is a PHP script this demo site uses to process image upload via form post:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | <?php include "include/db.php" ; // your db configuration // // Form post upload processor that requires explicit authentication. // // Response Protocol: // KEY|VALUE - one line, lines can be in any order // Keys: // STATUS - OK or ERROR, required // RECEIVED - number of bytes received, required // PROCESSED - number of bytes actually processed, required // DATE - server date/time when request was processed, optional // MSG - message from server (error or info), optional $uid = 0; $email = $_SERVER [ 'HTTP_USER_ID' ]; $pass = $_SERVER [ 'HTTP_USER_PASS' ]; $expected_bytes = (int) $_SERVER [ 'HTTP_STREAM_SIZE' ]; $f = $_FILES [ 'filename' ][ 'tmp_name' ]; $fsize = filesize ( $f ); $p = $_GET [ 'p' ]; if ( $email != null && $pass != null) { $sql = "select id from t_user where email = '{$email}' and password = '{$pass}'" ; if (! $result = $db ->query( $sql )) die ( $db ->error); if ( $result ->num_rows == 1) { $row = $result ->fetch_assoc(); $result ->free(); $uid = $row [ 'id' ]; } else { echo "RECEIVED|$fsize\r\n" ; echo "PROCESSED|0\r\n" ; echo "STATUS|ERROR\r\n" ; echo "MSG|Invalid Login\r\n" ; echo "DATE|" . date ( "Y-m-d H:i:s" ); return ; } $data = addslashes ( fread ( fopen ( $f , "r" ), $fsize )); if ( $expected_bytes == $fsize ) { $sql = "select count(*) as c from t_pic where user_id = $uid" ; if (! $result = $db ->query( $sql )) die ( $db ->error); $row = $result ->fetch_assoc(); $result ->free(); if ( $row [ 'c' ] > 0) { $sql = "update t_pic set pic{$p} = '{$data}' where user_id = {$uid}" ; } else { $sql = "insert into t_pic (user_id, pic{$p}) values ({$uid},'{$data}')" ; } $db ->query( $sql ); echo "RECEIVED|$fsize\r\n" ; echo "PROCESSED|$fsize\r\n" ; echo "DATE|" . date ( "Y-m-d H:i:s" ). "\r\n" ; echo "MSG|{$p}\r\n" ; echo "STATUS|OK" ; } else { echo "RECEIVED|$fsize\r\n" ; echo "PROCESSED|0\r\n" ; echo "STATUS|ERROR\r\n" ; echo "MSG|byte mismatch: [expected $expected_bytes, received: $fsize]\r\n" ; echo "DATE|" . date ( "Y-m-d H:i:s" ); } } else { echo "RECEIVED|$fsize\r\n" ; echo "PROCESSED|0\r\n" ; echo "STATUS|ERROR\r\n" ; echo "MSG|Incomplete Login Info\r\n" ; echo "DATE|" . date ( "Y-m-d H:i:s" ); } $db ->close(); ?> |
Here is a database used by the upload script above:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | -- MySQL dump 10.13 Distrib 5.5.31, for debian-linux-gnu (x86_64) -- -- Host: localhost Database: bambi -- ------------------------------------------------------ -- Server version 5.5.31-0ubuntu0.13.04.1 /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; /*!40101 SET NAMES utf8 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE= '+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE= 'NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; -- -- Table structure for table `t_pic` -- DROP TABLE IF EXISTS `t_pic`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `t_pic` ( `user_id` int (11) NOT NULL , `pic1` mediumblob, `pic2` mediumblob, `pic3` mediumblob, `pic4` mediumblob, `pic5` longblob, PRIMARY KEY (`user_id`), KEY `fk_user_id` (`user_id`), CONSTRAINT `fk_user_id` FOREIGN KEY (`user_id`) REFERENCES `t_user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION ) ENGINE=InnoDB DEFAULT CHARSET=latin1; /*!40101 SET character_set_client = @saved_cs_client */; -- -- Table structure for table `t_user` -- DROP TABLE IF EXISTS `t_user`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `t_user` ( `id` int (11) NOT NULL AUTO_INCREMENT, `email` varchar (45) NOT NULL , ` password ` char (32) NOT NULL , `date_created` datetime DEFAULT NULL , `fname` varchar (20) DEFAULT NULL , `lname` varchar (45) DEFAULT NULL , PRIMARY KEY (`id`), UNIQUE KEY `email_UNIQUE` (`email`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; /*!40101 SET character_set_client = @saved_cs_client */; -- Dump completed on 2013-06-03 15:00:12 |
Closing Remarks
Enabling Bambi-Editor on your website is easy. All you need are the following components:- A JNLP script pointing to your own config JAR and Bambi core release.
- Your own signed configuration JAR. In it you can include your custom plugins if you wrote any.
- Your upload processing script (if using formpost). You can use any language for this purpose. In our exaple we used PHP.
- Optionally, a database if you decide to save uploaded images into a blob.