Jump to content

help with upload form


mpsn

Recommended Posts

Hi, I want to check conditions for what is being uploaded. Basically I want to allow users to upload many XSD schema and XML file, so each complete upload is when user gives an 1 XSD file for 1 XML file to validate against, then the successful files are uploaded to db.

 

first page:(numUpload.html)

=======

<input type="text" name="numUploads"> to ask how many upload XSD:XML pairs they want, press SUBMIT goes to uploadForm.php

eg: if user types 2, then we have four upload forms (upload form for 1st XSD, upload form for 1st XML file; upload form for 2nd XSD file, upload form for 2nd XML file)

 

second page(uploadForm.php):

=====================

for loop to create each uploaded pair

then the validated XML (using the XSD of course) have their filenames inserted into db

press SUBMIT (goes to upload.php to validate each before entering the validated XML filenames to db)

 

You see, I want to have it organized where first upload form for first XSD:XML pair must be .xsd and second form of pair must be .xml

 

In short, this is what I need help to figure out how to code (the conditions to check before uploading):

==========================================

*1)for a given upload form pair, the first upload form only accepts .xsd, the second form only accepts .xml

2)no duplicate XML files allowed (XSD is ok)

3)if user uploads an .xsd, there must be an .xml

 

*eg for point 1)XSD#1[_________]  (Browse...)

                        XML#1[_________]  (Browse...)

                        ------------------------------------------

                        XSD#2 [_________]  (Browse...)

                        XML#2 [_________]  (Browse...)

 

Above is the upload forms I "drew", so I want to keep each pair as such where the first upload form for a given pair can only accept .xsd files and second form of a given pair of upload forms only accepts .xml files AND NO duplicate .xml files at all!

 

Any help much appreciated!

Link to comment
Share on other sites

On a user experience perspective, I think it would be better if there was an "Add XSD:XML Pair" button that adds inputs dynamically, instead of the first step where they have to type how many pairs they have. It can be easily done with Javascript, especially with the help of jQuery, which makes DOM manipulation a child's game.

 

On the real deal! File Inputs in PHP are treated with the $_FILES superglobal, which is an array. If square brackets are used in the name (like: photo[]), different file inputs with that same name are placed in the same array with different keys. It makes validation much easier. So, basically you'll need a form as the one below. You can omit the keys, but it will make things easier as by default vectors in PHP start with the index 0 (zero).

 

<form method="post" enctype="multipart/form-data">
<input type="file" name="xsd[1]"><br>
<input type="file" name="xml[1]">

<br><br>

<input type="file" name="xsd[2]"><br>
<input type="file" name="xml[2]">

<br><br>

<button type="submit">Send Files</button>
</form>

 

Once submitted, the $_FILES superglobal will become a multi-dimensional array that holds the filename, size, temporary location, etc, for each file. Make a form like the one above and add in the end of it a simple: print_r($_FILES). Then select some files, submit the form and inspect the contents of the array to understand how it works.

 

You can check for individual names using a code like below:

 

<?php
echo $_FILES['xsd']['name'][2]; //will output the second "xsd" filename
?>

 

You can check if a value is not empty to understand if a file was selected or not:

<?php
if ($_FILES['xsd']['name'][2]) {
echo 'Second XSD was selected';
}
?>

 

In the same fashion, you can check if pairs are complete (xsd and xml is set) by using a code similar to the one below. It's the answer for question number 3).

<?php
foreach ($_FILES['xsd']['name'] as $num=>$xsd) {
	$xml = $_FILES['xml']['name'][$num];

	//check for each one individually
	if (!$xsd) {
		echo "XSD $num was not selected";
	}
	if (!$xml) {
		echo "XML $num was not selected";
	}

	//or check for pairs
	if (!$xsd or !$xml) {
		echo "Pair $num is not complete";
	}
}
?>

 

To answer your question number 2), what kind of check you want to run, on filenames or content? Both aren't complicated, but depending on filesizes, checking on content can not be a very good idea. However, here you have the two options.

 

<?php
//check if filenames are different
$xml = $_FILES['xml']['name'];
$xml_unique = array_unique($xml);

if (count($xml) != count($xml_unique)) {
echo 'XML files should be unique';
}
?>

 

<?php
//check if file content is different
$xml = $_FILES['xml']['tmp_name'];
$file_contents = array();

foreach ($xml as $file) {
$file_contents[] = file_get_contents($file);
}

$file_contents = array_unique($file_contents);

if (count($xml) != count($file_contents)) {
echo 'XML files should be unique';
}
?>

 

For your question number 1), it is a simple procedure. You can use pathinfo() to get the extension of filenames and verify if they're .xml or .xsd.

 

<?php
$xsd = $_FILES['xsd']['name'];
$xml = $_FILES['xml']['name'];

foreach ($xsd as $num=>$filename) {
if (pathinfo($filename, PATHINFO_EXTENSION) != 'xsd') {
	echo "File $num is not a valid XSD file type";
}
}

foreach ($xml as $num=>$filename) {
if (pathinfo($filename, PATHINFO_EXTENSION) != 'xml') {
	echo "File $num is not a valid XML file type";
}
}
?>

 

It was a long one, but I hope you got things cleared up. It isn't very difficult really, but it needs some experience with multi-dimensional arrays and the $_FILES superglobal. Make some tests by yourself and by modifying the code I gave. You should get the thing you're working on up and running in no time :)

Link to comment
Share on other sites

Wow, that is what I call a answer! I did it this way:

 

here is pseudocode:

==============

make a xmlList to store only unique xmlFile from ($_FILES)

while still XSD:XML pairs to traverse, do:

if the ith xsdFile and ith xmlFile not empty, then:

  if the ith xsdFile is .xsd AND the ith xmlFile is .xml, then:

    foreach item in xmlList, do:

    if current xmlList item!=ith xmlFile, then:

      store the ith xmlFile's filename to db

      store ith xmlFile to xmlList

    END IF

  END FOREACH

  END IF

END IF

END WHILE

 

Here is code for 3rd script(upload.php), I have a hidden input type btw that stores the $_POST['numUploadsHidden'] (on the 2nd script: uploadform.php) from the first script where user types into textbox for total XSD:XML pairs BUT I'm not sure why it doesn't run, it DOES enter the BIG IF, but nothing else inside!

 

$numActualUploads=chop($_POST["numUploadsHidden"], "/");//chop removes char to right of first param string

if(isset($_POST["numUploadsHidden"])) {//LATER use:$_SESSION['..']=$_POST[]
$xmlList=array();//STORES current XML files (USED TO PREVENT INSERTING SAME FILENAME TO DB
for($i=0;$i<$numActualUploads;$i++) {//FOR EACH XSD:XML PAIR, DO:
	//CHECK EACH XSD:XML upload pair
	$curXSDFileName=$_FILES["uploadedXSDFile"]["name"][$i];
	$curXMLFileName=$_FILES["uploadedXMLFile"]["name"][$i];
	$curXSDFileExt=pathinfo($curXSDFileName,PATHINFO_EXTENSION);
	$curXMLFileExt=pathinfo($curXMLFileName,PATHINFO_EXTENSION);

	if(!empty($curXSDFileName) && !empty($curXMLFileName) ) {

		if($curXSDFileExt==".xsd" && $curXMLFileExt==".xml") {

			//IF xml file NOT in DB(check if on xmlList),
			foreach($xmlList AS $xmlItem) {
				if($xmlItem!=$curXMLFileName) {
					print $curXSDFileName.":".$curXMLFileName."<br />";
					$xmlList[]=$curXMLFileName;
				}
			}
		}
	}//END BIG IF
}//END FOR LOOP check each XSD:XML pairs
}//END BIG IF

 

**NOTE: I'm just printing it out at the moment for debugging! If you can take a look, thanks.

 

Link to comment
Share on other sites

Here is above code, more readable:

<?php
$numActualUploads=chop($_POST["numUploadsHidden"], "/");//chop removes char to right of first param string

if(isset($_POST["numUploadsHidden"])) {//LATER use:$_SESSION['..']=$_POST[]
$xmlList=array();//STORES current XML files (USED TO PREVENT INSERTING SAME FILENAME TO DB
for($i=0;$i<$numActualUploads;$i++) {//FOR EACH XSD:XML PAIR, DO:
	//CHECK EACH XSD:XML upload pair
	$curXSDFileName=$_FILES["uploadedXSDFile"]["name"][$i];
	$curXMLFileName=$_FILES["uploadedXMLFile"]["name"][$i];
	$curXSDFileExt=pathinfo($curXSDFileName,PATHINFO_EXTENSION);
	$curXMLFileExt=pathinfo($curXMLFileName,PATHINFO_EXTENSION);

	if(!empty($curXSDFileName) && !empty($curXMLFileName) ) {

		if($curXSDFileExt==".xsd" && $curXMLFileExt==".xml") {

			//IF xml file NOT in DB(check if on xmlList),
			foreach($xmlList AS $xmlItem) {
				if($xmlItem!=$curXMLFileName) {
					print $curXSDFileName.":".$curXMLFileName."<br />";
					$xmlList[]=$curXMLFileName;
				}
			}
		}
	}//END BIG IF
}//END FOR LOOP check each XSD:XML pairs
}//END BIG IF
?>

Link to comment
Share on other sites

First let's try refactoring your code and make it more readable.

 

<?php
if (isset($_POST['numUploadsHidden'])) {
//chop() is just an alias of rtrim(). Better use the original 
$_SESSION['numUploads'] = rtrim($_POST['numUploadsHidden'], '/');
}

if (isset($_SESSION['numUploads'])) {
//you're missing the step where file submissions is checked?

$num_uploads = $_SESSION['numUploads'];

$xml_list = array();

for ($i = 0; $i < $num_uploads; $i++) {
	$xsd_file = $_FILES['uploadedXSDFile']['name'][$i];
	$xml_file = $_FILES['uploadedXMLFile']['name'][$i];

	$xsd_ext = pathinfo($xsd_file, PATHINFO_EXTENSION);
	$xml_ext = pathinfo($xml_file, PATHINFO_EXTENSION);

	//skip the loop iteration if the pair is not complete.
	//use "break;" if you want to show a message and stop the loop completely.
	//you can show a message before "continue" too.
	if (!$xsd_file or !$xml_file) { continue; }

	//same idea as above.
	//it should be "xsd" or "xml", not ".xsd" or ".xml". Pathinfo doesn't return a dot.
	if ($xsd_ext != 'xsd' or $xml_ext != 'xml') { continue; }

	//in_array() checks if a value exists in an array. In your case, it will check
	//if the XML file exists in the XML List you got from the DB. If true, skip the loop.
	if (in_array($xml_file, $xml_list)) { continue; }

	//make the upload and whatever else here
}
}
?>

 

It does all the checks of the original code, but without nested if()s and a bit cleaner. Just add some debugging messages in there to see what part works and what not. It looks right from here, assuming that the form is constructed well. I have to declare it "closed" for tonight so I can't help any further until tomorrow. Maybe someone else will in the meantime.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.