?

Log in

No account? Create an account

Previous Entry | Next Entry

ScreenshotПонадобилось сделать достаточно очевидную, казалось бы, вещь - страничку, на которой можно заполнить несколько полей формы, выбрать несколько файлов и при нажатии на кнопку чтобы всё это вместе отправлялось на сервер без перезагрузки страницы (через ajax).

Оказалось, что есть ряд ньюансов. По отдельности нет проблем, а чтобы всё вместе - начинаются сложности. В итоге всё заработало, так что предлагаю простой пример.
После успешной загрузки сервер возвращает содержимое массивов _POST и _FILES, которое выводится на ту же страницу.

Проверял в Windows версиях FF, Chrome, IE, Opera, а также в Android Chrome и старом Android Browser.  Под IOS не проверял - нет под рукой.

Не работает в Safari 5.34/Win. Причина непонятна (симптомы - отправляет файлы нулевой длины).

Не будет работать в IE <9.

Код клиента (javascript):

<!DOCTYPE html>
<html>
<head>
<title>Ajax file and form data upload test by Frog</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">

$(document).ready(function(){

$('#cform').bind('submit', function(event)
{
    event.preventDefault();
    console.log('SUBMIT!');

    var formData = new FormData();

    $.each($("#cform_file")[0].files, function(i, file)
    {
        formData.append('file-'+i, file);
    });

    formData.append('name',$("#cform_name").val());
    formData.append('email',$("#cform_email").val());

    $.ajax({
            url: 'aftest.php',
            type: 'POST',
            contentType: false,
            processData: false,
            cache: false,
            headers: { 'cache-control': 'no-cache' }, // fix for IOS6 (not tested)
            dataType: 'json',
            data: formData,
            timeout: 7000,

            beforeSend: function(x)
            {
                console.log('beforeSend');
            },//beforeSend

            success: function( data )
            {
                console.log('success',data);

                if (data != null)
                {
                   $('#result').prepend(data._FILES);
                   $('#result').prepend(data._POST);
                }//if
                else
                {
                    console.log('success, but no data');
                }//else
            },//success

            error: function( data )
            {
               console.log('error');
            },//error

            complete: function( data )
            {
                console.log('complete');
            }//complete
    });//ajax()

})//submit()

});//.ready

</script>
</head>

<body>

<form id="cform" action="index.php" method="POST" enctype = "multipart/form-data">

Name: <input id="cform_name" name="cform_name" type="text" size="30" maxlength="30" /><br/>
E-Mail: <input id="cform_email" name="cform_email" type="text" size="30" maxlength="30" /><br/>

<input type="hidden" value="2000000" name="MAX_FILE_SIZE">
<input id="cform_file" type="file" size="20" name="cform_file[]" multiple=""><br/>
<!--
for single file upload replace with:
<input id="cform_file" type="file" size="20" name="cform_file">
-->
<br/>
<input id="cform_submit" name="cform_submit" type="submit" value="SEND" ><br/>

</form>

<hr>

<div id="result"></div>

</body>
</html>



Код сервера (php):

<?php

foreach($_FILES as $file)
{
    move_uploaded_file($file["tmp_name"], $file["name"]);
}//foreach

echo json_encode(  Array("_POST"=>'_POST ' . nl2br(print_r($_POST,true)), "_FILES"=>'_FILES ' . nl2br(print_r($_FILES,true)))  );
?>

Tags:

Comments

( 5 comments — Leave a comment )
eugene_ivanov
Nov. 19th, 2013 08:58 am (UTC)
давно уже существует http://www.phpletter.com/our-projects/ajaxfileupload/

cr_it
Nov. 19th, 2013 11:02 am (UTC)
То, что по вашей ссылке - просто отправляет файл. Без полей форм. Разница принципиальная.
eugene_ivanov
Nov. 19th, 2013 11:15 am (UTC)
там вторым параметром указывается форма, она пересылается вдобавок к файлу.

правда, файл только один, но доработать скрипт можно за пару минут для нескольких файлов.
eugene_ivanov
Nov. 19th, 2013 11:19 am (UTC)
вернее, там можно передать данные. они добавятся в форму для отправки:

ajaxFileUpload: function(s) {
s = jQuery.extend({}, jQuery.ajaxSettings, s);

var form = jQuery.createUploadForm(id, s.fileElementId, (typeof(s.data)=='undefined'?false:s.data));
arris_krain
Jan. 6th, 2014 06:44 pm (UTC)
я бы посоветовал вообще отключить кэширование аякс запросов в такой ситуации:

$.ajax( ...
cache: false, )
( 5 comments — Leave a comment )