views:

55

answers:

2

Hi All,

Been scratching my head for too long on this: Using jquery.form, (http://malsup.com/jquery/form) with PHP ... my $_FILES['someimage'] gets set but the error number is always UPLOAD_ERR_NO_FILE, size is also 0.

The JavaScript:

$('form input[type=file]').change(function(){
        $(this).clone().appendTo('#imgform');
        $('#imgform').ajaxForm();
        $('#imgform').ajaxSubmit(
            {
                type:'POST'
            }
        );
});

Which appends to:

<form id="imgform" method="POST" action="/api/images.php" enctype="multipart/form-data"></form>

From another form which has bog-standard file inputs.

PHP logs are clean, but var_dumping $_FILES always shows that the index is set to the name of the form element ... but no data.

Thanks guys! (Sorry, I know jQuery-like questions are too frequent round these parts).

EDIT I found http://stackoverflow.com/questions/415483/clone-a-file-input-element-in-javascript which contains further information and suggested alternatives.

What I decided to do is have a single form for non JavaScript browsers, and JavaScript/jQuery breaks the single form into three forms:

Head form -> File upload form -> tail form

Then I can post the file upload async, and when the tail's submit is clicked, glue the form together into a POST as they are just text fields.

A: 

You can't post files using ajax as javascript cannot access any local hard drive for security reasons.

There are ways to mimic ajax posting using iFrames. This link is a good example.

http://www.ajaxf1.com/tutorial/ajax-file-upload-tutorial.html

While this is "generally" true, the Malsup jQuery Form plugin supports "ajax" file uploads using a hidden iframe. Click the link poster provided and it describes how this is done.
BradBrening
Also, I missed it the first time around, but the issue with AJAX and file uploads isn't security related, it's due to the fact the forms with file uploads are sent using the enctype="multipart/form-data" parameter - which MIME encodes the submission. The XmlHTTPRequest (or equivalent) object does not support this.
BradBrening
@Tom - thanks for your post ... (however redundant :P )
Aiden Bell
+2  A: 

Two things I see when I try to run this. Since you are cloning then appending, I wonder if your file input exists within the context of the form. If not, then $('form input[type=file]') will never find the element to be cloned.

Perhaps the biggest problem, though, is in the way browsers handle file upload controls. You cannot programmatically set a value on a file input control - otherwise it would be trivial as a web developer to automatically set the file upload value to "c:\Files\MyPasswordFile.txt" and automatically submit the form invisibly to the user.

When I changed your code to this:

<input type="file" name="imageFile" />
<form id="imgform" method="POST" action="/api/images.php" enctype="multipart/form-data">

</form>

<script>
  $('input[type=file]').change(function() {
    alert("ACTION");
    $(this).clone().appendTo('#imgform');
    //$('#imgform').ajaxForm();
    //$('#imgform').ajaxSubmit(
    //        {
    //          type: 'POST'
    //        }
    //    );
  }); 
</script>

I can see the behavior as above - the field is cloned and appended - but it has no value. Since part of the clone process involves setting the field value - this would violate that security restriction and thus fails.

BradBrening
+1 So, cloning it remove its value .. interesting.
Aiden Bell
The situation is I have a form with an image upload. I want to upload the image, but not post the whole form. JS-less, the image will go with the main form but with JS, it is done async. Any ideas if I can't clone or move the node?
Aiden Bell
Can you place the file upload component in a seperate form?
BradBrening
@BradBrening - Thanks for your answer. I think what I will need to do is, using JS to be non obstructive, break the single form into 3 - head, file and tail. The others are just text, so I can glue them back together when a single submit is pressed. Also, further info in answer. Thanks again!
Aiden Bell