I wand to give the user the ability to upload as many pictures as he wants to. at present I hava a fexed amount of browse fields wich the user can use to select pictures... the code looks something like this :

<?PHP

$max_file_size = 3000000;

ECHO "<FORM NAME=name ID=name ACTION=submit.php enctype='multipart/form-data' METHOD=post >";

... code ...

ECHO "<input type='hidden' name='MAX_FILE_SIZE' value = $max_file_size > ";

	ECHO "<input id='file1' type='file' name='file[]'><BR>";
	ECHO "<input id='file2' type='file' name='file[]'><BR>";
	ECHO "<input id='file3' type='file' name='file[]'><BR>";

... code...

ECHO "<BR><INPUT TYPE = submit NAME = submit  VALUE = 'blah '>";

ECHO "</FORM>";

?>

On the other page I have code that builds a unick name for each uploaded picture, then makes a directory and copies the selected pictures in that directory.
This part works properly.

Then I have a few lines of code that build the link to each of those files in part and uploads it in to a DB... the website then accesses those pics via the links wich it takes from the DB.

Now on the DB, the images have their own table... it has two main columns... "largepic" and "smallpic". smmallpic is the thumbnail and largepic is the image that is displayed when users click on the thumbnail to view the full pic.

Now I need to figure out a way in wich to submit these pictures in groups of two. and process them in solid groups of two too.

SO I was thinking maybe on the upload page only two browse buttons would be shown... when the user fills bolth of them, another two apear beneath them (I'm guessing something like this can be done with ajax scripts somehow)... maybe with building the name of each field as a string first with a numeric value as part of the name that one can increment each time a new set of fields is needed.

But how do I go about the saving of the parh to the DB? the solid groups of two links need to be identifyable somehow so that you can target them when putting the links in the db since the first field needs to point to the first column and the second needs to point to the second.

If it was a set number of fields it would be easy to just write the upload proecess for each field... but for a limitless amount of fields ( namelly a new set of fields pops up as soon as the last set is filled... and, sheesh... lots of complications, if the user delets the pics in a field in the middlle of two other sets only that set of fields has to disapear and the others realocated... I am lost... )

How do you supose I could go about this unlimited image upload procedure?

Recommended Answers

All 12 Replies

use javascript for the automatic addition of "browse" field and javascript for the deletion.

you set up a numbering structure so that the thumbnail and full picture share a common filename,
the database only needs one picture name

the thumbnail is thumb100004.jpg
and the fullsize picture is 100004.jpg
the only thing needed is 100004.jpg
the thumbnail is
<img src='thumb<php echo'/*sql to get $number.jpg*/'; ?>' onclick='bigimage.src=<?php echo $number.jpg ?>'>

down the bottom of the page is
<img id='bigimage' src='blank.jpg'>
waiting to be filled with the contents of the clicked thumbnail

the thumbnail can be generated on the fly by php so only one file need be stored

dirty unchecked code, thought process only

For starters, if you name every field just like you have been, on the php side you will be able to access each individual file as a numerical array.

Now for adding and removing the file fields dynamically i'll refer you to my favorite prototype tutorial, which i have posted before: http://www.phpriot.com/articles Read the 8 Weeks of Prototype tutorials in order, even just look them over and at the examples and it should be easy to figure that out.

As for naming conventions, use a timestamp from time() or mktime() (although i believe mktime() throws an E_STRICT violation now). and add something unique, maybe the username to it etc.

Generally how i handle thumbnails is such:
First I create two directories, one that holds the large version and one that holds the thumbnails. 800 and 150 or full and thumb or anything that works with your conventions. I would caution against generating the thumbnails on the fly. Image processing can be very resource intensive and if you're displaying a lot of thumbnails on one page that will not scale well. disk space however is cheap and a lot easier to expand as necessary then more memory/processing power.

Then when i process the images i resize the uploaded file to the 800 and then resize the 800 to the 150, and save them both as the SAME filename but in different folders. This is where you will see the performance gain. You do two resizing operations and that is it for ever, unless of course you decide to change your thumbnail sizes.

In your case i'd say your best bet would be to create an "images" table in mysql and then use a many to many relationship to join a user to any number of images. In the images table simply storing some information about a particular image. filename, size? type? the date is was created?

//images
pk_imageid
filename
date_created

//users_images_join
fk_userid
fk_imageid

Or something like that.

When you pull all your images out, if you're displaying a thumbnail you use domain.com/images/150/filename.jpg and when you are displaying the full size domain.com/images/800/filename.jpg

Using a timestamp and a unique identifier, like a username (
1232375747_username.jpg) or userid (
1232375747_137.jpg) ensures that there is no way for two users to generate the same image, even if both of them would submit it at exactly the same time.

Here is a little something I use, It's rough and could be greatly improved but it works. One problem I notice is that the new div is created inside the previous so it keeps getting bigger and pushes everything below it down. That div is needed because or else the previous information in the input will be delete. But here it is work on it... let me know how it goes.

<script>
//n = name (upload)
//t = this input
//c = counter

function createNew(n,t,c){
	//counter NEXT
	c2 = c+1;
	
	//Start: Make input
	newer = "<input name='"+n+"_"+c2+"' type='file' onclick='javascript:createNew(\""+n+"\",this,"+c2+");' />";
	
	//End: New div for next
	newer += "<div id='Extras"+n+c2+"'>&nbsp;</div>";
	
	//Outputs whats created
	document.getElementById('Extras'+n+c).innerHTML += newer+"<br />";
	
	//Updates hidden counter
	document.getElementById(n+"count").value = c;
	
	//remove onclick
	t.onclick = "";
	
}
</script>

<form action="" method="post" />
&n<input name='upload_1' type='file' onclick='javascript:createNew("upload",this,1);' >
<div id="Extrasupload1">&nbsp;</div>
<input type='hidden' id='uploadcount' name='uploadcount' value='0' />
<input type="submit" value="Submit" />
</form>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<script type="text/javascript" src="jquery-1.3.min.js"></script>
<script type="text/javascript">
//Make sure the document is loaded
$(document).ready(function(){
	//Watch clicks on the add button
	$(":input[name='add']").click(function () { 
      $("div[id='file']:last").clone(true).insertAfter("div[id='file']:last");
	});
	
	//Watch clicks on the remove button
	$(":input[name='sub']").click(function () {
			$("div[id='file']:last").remove();
	});
 });
</script>

</head>

<body>
<form action="" method="post" enctype="multipart/form-data" name="form1" id="form1">
	<div id="file"><input type="file" name="file[]" id="file"/></div>
	<div id="file"><input type="file" name="file[]" id="file"/></div>
</form>
<div><input name="add" type="button" value="+ 1" /><input name="sub" type="button" value="- 1" /></div>
</body>
</html>

I know i posted a link to a prototype tutorial earlier, but this is a jQuery example, that is very basic but achieves the same thing posted above, and adds the ability to remove the last field too.

It could use some error checking, like checking if the only file field has been removed etc. Or creating a new file field if all of them have been deleted.

Just some food for thought but this is really javascript related not php.

thanks for the suggestion guys... I managed to skip a lot of headakes simply by doing the entire picture upload on a separate page. and I've got the upload working, the saving of files, placing in directory, naming, saving paths to DB, and accessing them from the website.

But now one more problem remains. for the admin there needs to be a checkbox next to each image detailing weather the image will display on the website or not. basicly there's a field in the DB that is either 1 or 0 and when the images are displayed on the website they check weather that field is 1 or 0... if it's 0 the pic is not displayed whille if the value is 1 the image is displayed.

I incorporated that checkbox in the file upload area so the user can choose weather to display the image on the website or not. but naturally he needs to have an option to edit that on the same page for each individual image.

so on the same page as the image upload, I made a for loop that will display all images that have a path in the DB.

INCLUDE('conect.php');


$sql_pics = "SELECT pics.smallpic, pics.largepic, pics.vizible, pics.ID
		        FROM pics
		        WHERE (pics.ID = '$VALUEl' )";

$rez_pics = mysql_query($sql_pics) OR DIE (mysql_error());

$lines_pics = mysql_num_rows($rez_pics);

FOR ($i=0; $i<$lines_pics; $i++)
	{	

	$smallpic = mysql_result ($rez_pics, $i, 'smallpic');
	$largepic = mysql_result ($rez_pics, $i, 'largepic');

	ECHO "<A HREF = '$largepic' target='_blank'> <IMG SRC = '$smallpic' BORDER='0'></IMG> </A><BR>";

        }

and for each of these pics I inclouded a checkbox that is either checked or unchecked based on what the vizible value is in the DB for each coresponding pic :

$vizible = mysql_result ($rez_pics, $i, 'vizible');

	IF ($vizible == 1)
		{
		ECHO "<INPUT TYPE='checkbox' NAME=viz ID=viz CHECKED='checked' > Vizible";
		}
	ELSE
		{
		ECHO "<INPUT TYPE='checkbox' NAME=viz ID=viz> Vizible";
		}

Now what I want to do is to implement a way in wich if the user checks or unchecks that checkbox, a function would be executed that will change the vizible field in the DB to 1 or 0 acording to weather the the checkbox is checked or not... and the results must be automaticly reloaded on the page... to that end I was thinking of using ajax scripts so that I wouldn't have to reload the entire page ( actually reloading the entire page isn't even an option )... so I was thinking of doing something like this (the $VALUE thing is necesary to identify wichset of pics the edited pic is from so that value must be transmitted through the ajax scripts):

<HTML>
<HEAD>

<script src="check.js"></script>

</HEAD>
<BODY>

<?PHP

ECHO "<span id='vize'>";

... entire code with displaying the images listed here ...

IF ($vizible == 1)
		{
		ECHO "<INPUT TYPE='checkbox' NAME=viz ID=viz CHECKED='checked' onMouseUp=\"vizib(this.value,'$IVALUE')\"> Vizible";
		}
	ELSE
		{
		ECHO "<INPUT TYPE='checkbox' NAME=viz ID=viz onMouseUp=\"vizib(this.value,'$VALUE')\"> Vizible";
		}

		ECHO "</span>";

?>
</BODY>
</HTML>

the check.js contains:

var xmlHttp

//-------------------------------

function vizib(str1,str2)
{ 
xmlHttp=GetXmlHttpObject()
if (xmlHttp==null)
 {
 alert ("Browser does not support HTTP Request")
 return
 }

var url="vizible.php"
url=url+"?q="+str1+"&p="+str2
url=url+"&sid="+Math.random()
xmlHttp.onreadystatechange=stateChangedviz 
xmlHttp.open("GET",url,true)
xmlHttp.send(null)

function stateChangedviz() 
{ 
if (xmlHttp.readyState==4 || xmlHttp.readyState=="complete")
 { 
 document.getElementById("vize").innerHTML=xmlHttp.responseText 
 } 
}

//----------------------------------

function GetXmlHttpObject()
{
var xmlHttp=null;
try
 {
 // Firefox, Opera 8.0+, Safari
 xmlHttp=new XMLHttpRequest();
 }
catch (e)
 {
 //Internet Explorer
 try
  {
  xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");
  }
 catch (e)
  {
  xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
  }
 }
return xmlHttp;
}

and the vizible.php contains:

<HTML>

<HEAD>
<script src="check.js"></script>
</HEAD>

<BODY>

<?PHP

INCLUDE('conect.php');

$q=$_GET["q"];

$p=$_GET["p"];

... code for updating the DB field vizible from the set marked by $p wich is $VALUE from the first file and put either 1 or 0 in it weather the checkbox si either checked or not ( reflected in the $q variable wich should hoald the checkbox's state. )

... code with displaying the images listed here allong with checkboxes and function links ...

?>

however... I get a number of problems with this aproach... first of all the escaped \" symbols seem to be interfearing with the function somehow as it won't execute...

also... this.value for a checkbox always seems to return "on" reguardless if the checkbox is checked or not...

and I'm not sure that transfering 2 variables through the ajax scripts works the way I typed above...

any suggestions for this?

</BODY>
</HTML>

Starting from scratch with AJAX is completely unnecessary.
There are many fine Javascript libraries that exist for this reason.

Again I recommend you look at jQuery or Prototype.

This is not a solution for your issue but is an example that you should be able to manipulate to get your result:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.1/jquery.min.js"></script>
<script type="text/javascript">
//Wait for the document to be ready
 $(document).ready(function(){

   //Listen for a click on every checkbox
   $("input:checkbox").click(function () { 
   		var val = $(this).val();
		var name = $(this).attr('name');
                //This is so IE does not cache the results
		var noCache = new Date();
                
                //Make a JSON request
   		$.getJSON('ajax.php', {'item':name, 'val':val, '_':noCache.getTime()}, function(json){
			$("[name='" + json.item + "']").attr('value', json.check )	
		});

    });
	
        //Change the value of the checkbox to 1 or 0
	function updateElement(json)
	{
		//Update the checkbox and change the value status
		 $("[name='" + json.item + "']").attr('value', json.check )	
	}
 });
	
</script>
</head>
<body>

Item 1 <input type="checkbox" name="1" id="viz" value="0"/> <br />
Item 2 <input type="checkbox" name="2" id="viz" value="0"/> <br />
Item 3 <input type="checkbox" name="3" id="viz" value="0"/> <br />
Item 4 <input type="checkbox" name="4" id="viz" value="0"/> <br />
</body>
</html>

And now for php file:

<?php

//Make sure we aren't caching this file
header('Cache-Control: no-cache, must-revalidate');
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Content-type: application/json');

//Do some sql statements etc, and make the necessary changes using the get item value etc.

//return some json for demonstration

$val = 0;
if( $_GET['val'] == 0)
{
	$val = 1;
}

$arr = array (
		'item'=>$_GET['item'],
		'check'=>$val
);

echo json_encode($arr);

I'm having a hard time figuring out what is going on in there... but anyways... can somebody please tell me how I could get the value of a checkbox when the user clicks it?

I tryed onclick function(this.value) or on mouseup function ( this.value)

and tryed echoing it on the file the function would open...

but this.value for the checkbox ALWAYS returned "on" reguardless if it was checked or not...

wich leads me to either think that it was only executing the function ONCE when the user first clicked the checkbox and then for some reason it didn't fire no matter how many times the user would re-click it...

or that this.value always returns on for the checkbox reguardless what state it is in...

so, can anybody give me a clue about this?

I'm not seeing whats so difficult with the code i posted.
I tend to believe the problem is, you don't want to look at, and apply the concepts to your code, you simply want the exact solution to your problem.

The code I posted not only handles the click events on EVERY checkbox on the page but also provides the mechanisms for capturing the value of the checkbox and the name of the field.

It also handles the AJAX request. The only difference is I used a function designed for returning JSON as an example of the flexibility you gain by working with a javascript library. You could just as simply make an ajax call with $.ajax and return xml or anything else you would like.

If my solution doesn't appease you, then I would suggest having a look here.

commented: goodonyer, its a helpscreen, too many people wont do any part of the fix for themselves +1

I tryed your example... it dosen't do anything. just displays the checkboxes and clicking on them will do nothing.

<script type="text/javascript">
//Wait for the document to be ready
 $(document).ready(function(){

   //Listen for a click on every checkbox
   $("input:checkbox").click(function () { 
   		var val = $(this).val();
		var name = $(this).attr('name');
                //This is so IE does not cache the results
		var noCache = new Date();
                
                //Make a JSON request
   		$.getJSON('ajax.php', {'item':name, 'val':val, '_':noCache.getTime()}, function(json){
			$("[name='" + json.item + "']").attr('value', json.check )	
		});

    });
 });
	
</script>

Well let me go through it and try to explain it better.
in jQuery the $.(document).ready() function is setup immediately following initialization of the DOM.
So the code sits in there so it can be used even before the actual content on the page is loaded.

The main workhorse is this function:

//Listen for a click on every checkbox
   $("input:checkbox").click(function () { 
   		var val = $(this).val();
		var name = $(this).attr('name');
                //This is so IE does not cache the results
		var noCache = new Date();
                
                //Make a JSON request
   		$.getJSON('ajax.php', {'item':name, 'val':val, '_':noCache.getTime()}, function(json){
			$("[name='" + json.item + "']").attr('value', json.check )	
		});

what this does is says listen for a click event on every input type of checkbox. On a click of any checkbox its runs the function contained in that code.

it gets the value of the checkbox that was just checked $.(this).val();
and also grabs the name of the field.

In my exampe I made the name unique for each checkbox and then set a default value of 0 indicating it was not display.

the noCache is just a date object so that IE does not cache the GET request.

$.getJSON() setups the ajax request for ajax.php. {'item':name, ... } is the query parameters.
This function ultimately requests: ajax.php?item=fieldname&val=checkboxvalue&_{timestamp}

ajax.php in my example simply is looking for a get variable and then encoding a basic php array into JSON and then echoing the JSON to the stream.

$.getJSON returns a JSON object by default so we can simply navigate it with jQuery.

the last attribute is the function to call on a successful ajax request. In this case i specified it right in the $.getJSON function.

it just looks for an element with the name id of the one submitted and then updates its value according to the JSON response. in this case changes 0 to 1 or 1 to 0.

Thats all there is too it, like i said its not the perfect response to your problem but it does do everything you wanted. Depending on your php version etc we can also work without the JSON.

Use php to initially draw the form, and you dont need to inject any javascript into the elements themselves. This makes for much cleaner code.

Hopefully this helps break it down some more.
I apologize because i left an early function (updateElement) in my previous example and its not needed.

Please feel free to ask any more specific questions and I'll try to help you get started with jQuery which if you're relying on ajax and/or javascript will dramatically improve your time, i know it did for me.

thank you for taking the time to explain this indeapth. I apreciate it. I still am not sure exactly how to apply this, but I'm sure some experimentation will solve that.

In the meantime I decided to use a more primitive solution to the whole problem, and jsut relayed on form submits with clicking a button instead of a checkbox. wich redirects to a page, executs the queries, updates the DB and then redirects back to the original page. the page is not expected t ohavem ore then 10 thumbnails on it at any time, so even though it might seem like a bad idea, I tested it and it seems to work ok. I'll look to updating this in the future using this example.

In the meantime, I noticed you mentioned using code before the content of the page is loaded.

This is also something I'm interested in since I'm planning to restrict access to part of the webpage by a autentification mesage where the user should type in their username and password.

the way I imagined this was that when the user would try to access the first page of the restricted part of the page, a pupul would apear whenre he would be needed to type in his password. if the password is wrong he would be redirected to the last page he was on, if it's corect he can go on. also if he tryes to load a page after the first restricted page like manually typing

site/restricted_page/something.php

he would be redirected to the first restricted page where the login message would happen. jsut to prevent unauthorised access. of course for that a value would probably need to be checked if he HAS entered a corect password so that he won't be redirected even if he did enter it.

this is what I think it should work like, but the first thing that I don't know about this is how to handle the login popup. is there a way to generate one of those standard type messages like alerts or those yes and no messages but with two fields and a submit button on them? or should I relly on making an actual popup page with those fields on it.

I'm thinking that all this should happen before the content of the page loads... so that if it's an unauthorised user, he won't get to see anything.

Any ideas?

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.