1

I have a form that works in Firefox and Chrome, but not Internet Explorer 8. It's got some text inputs and one file input: it's the file input that isn't working.

The problem seems to be that the server isn't getting the file at all. The server throws MultiValueDictKeyError because my view is trying to look up the element with the file in it, and it's not present in request.FILES.

I checked the IE developer tools and the input element is holding the file when the form submits. Something else is going on.

There is one curveball in the form: I'm using a styled input button using help from this thread

My HTML, plus some inline js:

<form action="{{ order.get_absolute_url }}load/" method="post" enctype="multipart/form-data" class="med order" id="order_form" name="order_form">
    <div class="card form_wrapper float_left">
        <h2 class="section_header">{{ order.order_number }} - Add Homeowners<span class="status_label">{{ order.get_current_status_display }}</span></h2>
        <table id="certified_one_off_table" class="residents">
            <thead>
                <tr>
                    <th>Owner Name<span class="ho_required_note">*</span></th>
                    <th>Co-owner Name</th>
                    <th>Account #<span class="ho_required_note">*</span></th>
                    <th>Address<span class="ho_required_note">*</span></th>
                    <th>Address, Continued</th>
                    <th>City, State Zip<span class="ho_required_note">*</span></th>
                    <th>Letter file<span class="ho_required_note">*</span></th>
                </tr>
            </thead>
            <tbody>
                <tr class="ho_load_row">
                    <td>
                        <input type="text" name="ho_owner-1" value="" class="ho_owner ho_load_field ho_required" />
                    </td>
                    <td>
                        <input type="text" name="ho_co_owner-1" value="" class="ho_co_owner ho_load_field" />
                    </td>
                    <td>
                        <input type="text" name="ho_account_id-1" value="" class="ho_account_id ho_load_field ho_required" />
                    </td>
                    <td>
                        <input type="text" name="ho_mailing_address-1" value="" class="ho_mailing_address ho_load_field ho_required" />
                    </td>
                    <td>
                        <input type="text" name="ho_mailing_address_contd-1" value="" class="ho_mailing_address ho_load_field" />
                    </td>                    
                    <td>
                        <input type="text" name="ho_mailing_csz-1" value="" class="ho_mailing_csz ho_load_field ho_required" />
                    </td>
                    <td id="upload_button_cell">
                        <div id="certified_upload_button" class="new_button" onclick="getFile(this)">Upload</div>
                        <div style='height: 0px;width: 0px; overflow:hidden;'><input id="id_ho_document-1" name="ho_document-1" type="file" class="ho_file ho_load_field ho_required" /></div>
                    </td>
                    <td id="validate_cell">
                        <img id="id_ho_document_valid-1" src="/public/img/cross.png" alt="Invalid or no document selected" />
                    </td>
                </tr>
                <tr>
                    <td colspan="6">
                        <a id="certified_add_ho" href="#">Add Another Homeowner &rarr;</a>
                    </td>
                </tr>
            </tbody>
            <tfoot>
            <tr>
                <td colspan="6">
                    <br />
                        <center><input type="submit" id="certified_one_off_button" class="new_button_disabled" value="Approve Order for these Homeowners" disabled="disabled" /></center>
                    <br />
                </td>
            </tr>
            </tfoot>
        </table>
    </div>
</form>
<script type="text/javascript">
function getFile(obj) { $(obj).siblings('div').children('input').click(); }
</script>

Snippet of the view code:

if request.method == 'POST': 
    order_quantity = 0
    for row_number in xrange(1, len(request.POST)):
        if 'ho_owner-{0!s}'.format(row_number) not in request.POST:
            break

        document = request.FILES['ho_document-{0!s}'.format(row_number)]

edit: forgot the js that validates the form and enables the submit button

$(document).ready(function() {
  function update_certified_one_off_button() {
    var invalid_fields = 0
    $('.ho_load_field.ho_required').each(function() {
        if ($(this).val() === '') {
            invalid_fields += 1;
            $(this).css('background-color', '#fff2f2');
        } else {
            $(this).css('background-color', '#ffffff');
        }
    });
    $('input[name^="ho_document-"]').each(function() {
      var ext = $(this).val().split('.').pop().toLowerCase();
      if($.inArray(ext, ['pdf']) == -1) {
          invalid_fields += 1;
      }         
    });

    var submit_button = $('#certified_one_off_button');
    if (invalid_fields > 0) {
        submit_button.addClass('new_button_disabled');
        submit_button.removeClass('new_button');
        submit_button.attr('disabled', 'disabled');
    } else {
        submit_button.addClass('new_button');
        submit_button.removeClass('new_button_disabled');
        submit_button.removeAttr('disabled');
    }
  }

  function certified_validate(event) {
    var old_name_full = $(event.target).attr('id').split('-');
    var old_name = old_name_full[0];
    var old_num = parseInt(old_name_full[1]);

    var icon = $("#id_ho_document_valid-" + String(old_num));     
    var ext = $(event.target).val().split('.').pop().toLowerCase();
    if($.inArray(ext, ['pdf']) == -1) {
      icon.attr('src', '/public/img/cross.png');
      alert('Only PDF format documents will be accepted.');
    } else {
      icon.attr('src', '/public/img/tick.png');
    }
  }

  $('#certified_add_ho').click(function(e) {
      e.preventDefault();

      var last_row = $('.ho_load_row').last();
      last_row.after('<tr class="ho_load_row">' + last_row.html() + '</tr>');

      var last_row_img = $('.ho_load_row').last().find('img');
      var old_name_full = last_row_img.attr('id').split('-');
      var old_name = old_name_full[0];
      var old_num = parseInt(old_name_full[1]);
      last_row_img.attr('id', old_name + '-' + String(old_num + 1));
      last_row_img.attr('src', '/public/img/cross.png');         

      var last_row_inputs = $('.ho_load_row').last().find('input');
      last_row_inputs.each(function() {
        $(this).val('').find('.default').attr('selected', 'selected');  

        old_name = $(this).attr('name').split('-')[0];
        $(this).attr('name', old_name + '-' + String(old_num + 1));

        var old_id = $(this).attr('id'); 
        if (old_id) {
          old_id = old_id.split('-')[0];
          $(this).attr('id', old_id + '-' + String(old_num + 1));
        }
      });

      $("#id_ho_document-" + String(old_num + 1)).change(certified_validate);

      $('.ho_load_field.ho_required').bind('change keyup', update_certified_one_off_button);
      update_certified_one_off_button();
  });

$('#order_form .ho_load_field').bind('change keyup', update_certified_one_off_button);
$("#id_ho_document-1").change(certified_validate);  
});

edit 2: I managed to capture my http request using a 3rd party tool, and it looks like my file never leaves the machine:

POST /order/ndVKUeCRT1/load/ HTTP/1.1
Accept: application/x-ms-application, image/jpeg, application/xaml+xml, image/gif, image/pjpeg, application/x-ms-xbap, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-shockwave-flash, */*
Referer: http://eiger.optimaloutsource.com:8088/order/ndVKUeCRT1/load/
Accept-Language: en-US
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET4.0C; .NET4.0E)
Content-Type: multipart/form-data; boundary=---------------------------7dc1bd1f60702
Accept-Encoding: gzip, deflate
Host: eiger.optimaloutsource.com:8088
Content-Length: 899
Connection: Keep-Alive
Cache-Control: no-cache
Cookie: sessionid=0a37e24c25c4b7716249c50eb52b523a; __utma=133342874.1270580592.1320187097.1340128445.1340141010.4; __utmz=133342874.1340055122.2.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); __utmb=133342874.2.10.1340141010; __utmc=133342874

-----------------------------7dc1bd1f60702
Content-Disposition: form-data; name="ho_owner-1"

phasetwenty
-----------------------------7dc1bd1f60702
Content-Disposition: form-data; name="ho_co_owner-1"


-----------------------------7dc1bd1f60702
Content-Disposition: form-data; name="ho_account_id-1"

account
-----------------------------7dc1bd1f60702
Content-Disposition: form-data; name="ho_mailing_address-1"

address
-----------------------------7dc1bd1f60702
Content-Disposition: form-data; name="ho_mailing_address_contd-1"


-----------------------------7dc1bd1f60702
Content-Disposition: form-data; name="ho_mailing_csz-1"

city, CA 90000
-----------------------------7dc1bd1f60702
Content-Disposition: form-data; name="ho_document-1"; filename=""
Content-Type: application/octet-stream


-----------------------------7dc1bd1f60702--


HTTP/1.1 500 INTERNAL SERVER ERROR
Date: Tue, 19 Jun 2012 21:25:31 GMT
Server: Apache/2.2.14 (Ubuntu)
Vary: Cookie
Connection: close
Content-Type: text/html; charset=utf-8

How can I get IE to submit this form correctly?

Community
  • 1
  • 1
Chris
  • 3,438
  • 5
  • 25
  • 27

2 Answers2

1

IE (all versions, even IE9) is quite sensitive to all 'untrivial' manipulations with the file input. In your code I see that you trigger the click on this input artificially (that's what function getFile(obj) do), but that's not allowed in IE.

Instead try to use the following technique: leave your file input dimensions as is, but make it transparent - and place something more good-looking 'underneath' it. It's described here well enough, for example.

raina77ow
  • 103,633
  • 15
  • 192
  • 229
  • That sounds plausible. I'll try it. – Chris Jun 19 '12 at 21:40
  • By the way, there's a very useful plugin called [uniform](http://uniformjs.com/) which greatly simplifies styling all the inputs - including the file' one. ) – raina77ow Jun 19 '12 at 21:42
0

You need to remove the disabled attribute of the submit button in order for the script to be able to click it. Alternately, submit the form using JavaScript directly with document.order_form.submit().

Diodeus - James MacFarlane
  • 112,730
  • 33
  • 157
  • 176
  • Ah, actually the validation of the form is happening in javascript which I left out. I'll edit the post to include it. Currently the submit button works in all browsers. – Chris Jun 19 '12 at 20:24