3

Я использую Fine Uploader (v5.0.1) с jQuery, jQuery.validate и jQuery.form плагинами для многополевой формы для новых событий, которые могут иметь от 0 до 2 вложений файлов.Точный загрузчик с вопросами о форме формы

У меня есть работа, но у меня есть несколько вопросов, прежде чем идти дальше.

  1. Мой клиентский код генерирует один POST-запрос для каждого файла (включая другие элементы формы) плюс один дополнительный запрос POST только для других элементов формы. Итак, если у моей формы есть два вложения файлов, я получаю три запроса POST. Это нормальное поведение? Могу ли я получить все в одном запросе POST?
  2. Если несколько запросов POST являются обычным явлением, мне нужно будет генерировать какой-то уникальный идентификатор на клиенте до первого запроса POST, поэтому я могу избежать дублирования записей событий в моей базе данных и связать каждую загрузку файла с помощью правильное событие. Если это направление, в котором я должен идти, есть ли примеры такого типа реализации, на которые я могу смотреть?
  3. Если файлы не прикреплены, я получаю диалоговое окно предупреждения: «Нет файлов для загрузки». Форма может быть отправлена ​​без прикрепленных файлов, поэтому я не хочу указывать пользователю, что он должен прикреплять файлы. Как я могу избавиться от этого диалога?
  4. В настоящее время я получаю один ответ POST для данных формы плюс один ответ POST для каждого загруженного файла. Есть ли способ обработать только окончательный ответ POST (например, form.onAllComplete)? Что делать, если форма не имеет прикрепленных файлов?
  5. Я использую одну конечную точку сервера для формы, включая загрузку файлов. Должен ли я использовать две отдельные конечные точки, одну для полей другой формы и одну для загрузки файлов?

Вот моя форма: http://www.paulrachal.com/test/fineuploader-test.htm

Вот мой код: Клиент:

<!DOCTYPE html> 
<html> 
    <head> 
    <meta charset="utf-8"> 
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0"> 
    <title>New Event</title> 
    <link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.0/jquery.mobile-1.4.0.min.css" /> 
    <script src="http://code.jquery.com/jquery-1.10.2.min.js"></script> 
    <script src="http://code.jquery.com/mobile/1.4.0/jquery.mobile-1.4.0.min.js"></script> 
    <script src="http://ajax.aspnetcdn.com/ajax/jquery.validate/1.13.0/jquery.validate.min.js"></script> 
    <script src="http://malsup.github.com/jquery.form.js"></script> 
    <!-- Fine Uploader --> 
    <link rel="stylesheet" href="../css/custom.fineuploader-5.0.1.min.css" /> 
    <script src="../js/custom.fineuploader-5.0.1.min.js"></script> 
    <!-- document.ready --> 
    <script type="text/javascript" charset="utf-8"> 
    $(document).ready(function(){ 
    <!-- event handlers --> 
    // hide the file upload button when the page loads 
    $('#manual-fine-uploader').hide(); 
    // show the file upload button on change in attachments checkbox 
    $("#hasattachments").change(function() { 
     if ($('#hasattachments:checked').length) { 
      $('#manual-fine-uploader').show(); 
     } 
     else { 
      $('#manual-fine-uploader').hide(); 
     } 
    }) 
    <!-- Fine Uploader setup --> 
    var manualuploader = $('#manual-fine-uploader').fineUploader({ 
     request: { 
     endpoint: 'fineuploader-test.php' 
     }, 
     form: { 
      element: 'new-event' 
     }, 
     template: "qq-template-manual-noedit", 
     validation: { 
     allowedExtensions: ['txt', 'pdf'], 
     itemLimit: 2, 
     sizeLimit: 256000 // 250 kB = 250 * 1024 bytes 
     }, 
     autoUpload: false 
    }); 
    <!-- form validation --> 
    // setup form validation on the form element 
    $("#new-event").validate({ 
    // validation rules 
    rules: { 
     description: { 
      required: { 
       depends: function(element) { 
        if ($("input[name='eventtype']:checked").val() == "3" || $("input[name='eventtype']:checked").val() == "4" || $("input[name='eventtype']:checked").val() == "5") 
        return true; 
       } 
      } 
     }, 
    }, 
    // validation error messages 
    messages: { 
     description: "Please enter a description" 
    }, 
    // submit handler 
    submitHandler: function(form) { 
     $("#send").attr("value", "Sending..."); 
     $(form).ajaxSubmit({ 
     target: "#response", 
     dataType: "json", 
     success: function processJson(response) { 
      if (response.success) 
      { 
       $(form).slideUp("fast"); 
       $("#response").html("<span class='success'>" + response.success + "</span>").hide().slideDown("fast"); 
      } // end if 
      else if (response.failure) 
      { 
       $("#response").empty(); 
       $(".error").removeClass("error"); 
       $errors = response.failure; 
       for ($i = 0; $i < $errors.length; $i++) { 
        $error = $errors[$i]; 
        $.each($error, function(key, value) { 
         // append error text to div#response 
         $("#response").append("<li class='failure'>" + value + "</li>").hide(); 
         // set form elements based on the error 
         switch(key) { 
          case "description-isempty": 
           $("#description").addClass("error"); 
           break; 
          case "eventname-isempty": 
           $("#eventname").addClass("error"); 
           break; 
          case "eventtype-isinvalid": 
           $("#eventtype-input").addClass("error"); 
           break; 
          default: 
           // default statements if no cases are true 
         } // end switch 
        }); // end $.each 
       } // end for 
       $("#response").addClass("failure"); 
       $("#response").slideDown("fast"); 
       $("html, body").animate({ scrollTop: 0 }, "fast"); 
      } // end else if 
     } // end processJson 
     }); 
     return false; 
    } 
    }); // end #new-event.validate 
    <!-- validate individual fields on change --> 
    // #description 
    $('#description').on('change', function() { 
     $('#new-event').validate().element('#description'); 
    }); 
    }); // end document.ready 
    </script> 
    <!-- Fine Uploader Template --> 
    <script type="text/template" id="qq-template-manual-noedit"> 
    <div class="qq-uploader-selector qq-uploader"> 
     <div class="qq-upload-drop-area-selector qq-upload-drop-area" qq-hide-dropzone> 
      <span>Drop files here to upload</span> 
     </div> 
     <div class="qq-upload-button-selector qq-upload-button"> 
      <div>Browse...</div> 
     </div> 
     <span class="qq-drop-processing-selector qq-drop-processing"> 
      <span>Processing dropped files...</span> 
      <span class="qq-drop-processing-spinner-selector qq-drop-processing-spinner"></span> 
     </span> 
     <ul class="qq-upload-list-selector qq-upload-list"> 
      <li> 
       <div class="qq-progress-bar-container-selector"> 
        <div class="qq-progress-bar-selector qq-progress-bar"></div> 
       </div> 
       <span class="qq-upload-spinner-selector qq-upload-spinner"></span> 
       <span class="qq-upload-file-selector qq-upload-file"></span> 
       <span class="qq-upload-size-selector qq-upload-size"></span> 
       <a class="qq-upload-cancel-selector qq-upload-cancel" href="#">Cancel</a> 
       <span class="qq-upload-status-text-selector qq-upload-status-text"></span> 
      </li> 
     </ul> 
    </div> 
    </script> 
    <!-- styles --> 
    <style type="text/css"> 
    .qq-upload-button-selector { 
     background: #0080FF; 
    } 
    #response { 
     margin-bottom: 20px; 
     text-align: center; 
    } 
    #response .success { 
     color: #08a300; 
    } 
    #response .failure { 
     color: #dc0000; 
    } 
    div.failure { 
     background-color: #FF0; 
    } 
    .error { 
     border: 2px solid red; 
    } 
    input.error { 
     border: 2px solid red; 
    } 
    select.error { 
     border: 2px solid red; 
    } 
    </style> 
    </head> 
    <body> 
    <!-- new-event-form --> 
    <div id="new-event-form" data-role="page"> 
    <!-- header --> 
    <div data-role="header"><h1>NEW EVENT</h1></div> 
    <div class="content" data-role="content"> 
    <div id="response"></div> 
    <form id="new-event" action="fineuploader-test.php" method="post"> 
    <div data-role="fieldcontain"> 
     <fieldset data-role="controlgroup"> 
      <legend>Event Type:</legend> 
      <div id="eventtype-input"> 
       <input type="radio" name="eventtype" id="eventtype_1" value="1" checked="checked" /> 
       <label for="eventtype_1">Ride</label> 

       <input type="radio" name="eventtype" id="eventtype_2" value="2" /> 
       <label for="eventtype_2">Clinic</label> 

       <input type="radio" name="eventtype" id="eventtype_3" value="3" /> 
       <label for="eventtype_3">Social Event</label> 

       <input type="radio" name="eventtype" id="eventtype_4" value="4" /> 
       <label for="eventtype_4">Meeting</label> 

       <input type="radio" name="eventtype" id="eventtype_5" value="5" /> 
       <label for="eventtype_5">Non-Club Event</label> 
      </div> 
     </fieldset> 
    </div> 
    <div data-role="fieldcontain"> 
     <label for="eventname">Event Name:</label> 
     <input type="text" name="eventname" id="eventname" value="" maxlength="40" required /> 
    </div> 
    <div id="descriptioninput" data-role="fieldcontain"> 
     <label for="description">Description:</label> 
     <input type="text" name="description" id="description" value="" maxlength="40" /> 
    </div> 
    <div id="attachments" data-role="fieldcontain"> 
     <fieldset data-role="controlgroup"> 
      <legend>Attachments:</legend> 
       <input type="checkbox" name="hasattachments" id="hasattachments" value="1" /> 
       <label for="hasattachments">Attachments</label> 
     </fieldset> 
    </div> 
    <div id="manual-fine-uploader">Browse...</div> 
     <div class="ui-body ui-body-b"> 
     <fieldset class="ui-grid-a"> 
      <div class="ui-block-a"><input type="reset" data-theme="d" value="Cancel"></div> 
      <div class="ui-block-b"><input type="submit" data-theme="a" value="Submit"></div> 
     </fieldset> 
     </div> 
    </form> 
    </div> <!-- /content --> 
    </div> <!-- /page --> 
    </body> 
</html> 

Сервер:

<?php 

// get values from POST request 
$eventtype = $_POST['eventtype'];   // eventtype field 
$eventname = $_POST['eventname'];   // eventname field 
$description = $_POST['description'];  // description field 
$hasattachments = $_POST['hasattachments']; // hasattachments field 
$qqfile = $_POST['qqfile'];     // file upload field 
$qquuid = $_POST['qquuid'];     // file upload uuid 
$qqfilename = $_POST['qqfilename'];   // file upload filename 

// include the upload handler class 
require_once "handler.php"; 
// initialize errors array 
$errors = array(); 
// validate elements 
// eventtype 
$eventtypes = array_flip(array('1', '2', '3', '4', '5')); 
if (!isset($eventtypes[$eventtype])) $errors = addError("eventtype-isinvalid"); 
// eventname 
$eventname = filter_var($eventname, FILTER_SANITIZE_STRING); 
if(empty($eventname)) $errors = addError("eventname-isempty"); 
// description 
$description = filter_var($description, FILTER_SANITIZE_STRING); 
if (empty($description)) $errors = addError("description-isempty"); 
// file uploads 
if ($hasattachments == 1) uploadFiles(); 
// functions 
// add error 
function addError($error) { 
    switch ($error) 
    { 
     case "description-isempty": 
      $errors[] = array("description-isempty" => "Please enter a description."); 
      break; 
     case "eventname-isempty": 
      $errors[] = array("eventname-isempty" => "Please enter an event name."); 
      break; 
     case "eventtype-isinvalid": 
      $errors[] = array("eventtype-isinvalid" => "Please select an event type."); 
      break; 
    } // end switch($error) 
    return $errors; 
} // end function addError() 
// file uploads 
function uploadFiles() { 
    $uploader = new UploadHandler(); 
    // specify the list of valid extensions 
    $uploader->allowedExtensions = array("txt", "pdf"); 
    // specify max file size in bytes 
    $uploader->sizeLimit = 250 * 1024; // 250 kB 
    // specify the input name set in the javascript. 
    $uploader->inputName = "qqfile"; // matches Fine Uploader's default inputName value by default 
    // specify the folder to temporarily save parts to use the chunking/resume feature 
    $uploader->chunksFolder = "chunks"; 
    $method = $_SERVER["REQUEST_METHOD"]; 
    if ($method == "POST") { 
     header("Content-Type: text/plain"); 
     // call handleUpload() with the name of the folder, relative to PHP's getcwd() 
     $result = $uploader->handleUpload("uploads/"); 
     // get the name used for uploaded file 
     $result["uploadName"] = $uploader->getUploadName(); 
    } // end if 
} // end function uploadFiles() 

// return response 
if (!empty($errors)) $response = array("failure" => $errors); 
else $response = array("success" => "Success! Your event has been posted."); 
echo json_encode($response); 

?> 
+1

Возможно, вы захотите урезать свой вопрос до минимально воспроизводимого примера. –

+0

Не воспроизводится? Вот почему я предоставил ссылку на рабочую форму. – paulr

+1

Ни один из ваших образцов кода не является хорошим кандидатом на инструмент стека для стека, особенно второй. Ни один из них не является исполняемым и не должен быть. Обычно я рекомендую людям забывать, что фрагменты стека существуют, поскольку они редко подходят, и в любом случае существуют альтернативы вне переполнения стека (например, jsbin). –

ответ

2

Отвечая на ваши вопросы по порядку:

  1. Точный загрузчик отправляет каждый файл в отдельный запрос, и нет возможности изменить это.
  2. Fine Uploader уже генерирует уникальный идентификатор (UUID) для каждого файла. Этот идентификатор отправляется с запросом на загрузку. Если вы хотите отправить дополнительные данные для файла, вы можете сделать это через setParams API method. Это отправит дополнительные пользовательские параметры по вашему выбору вместе с файлом. Вы можете указать новые параметры для всех файлов или определенного файла.
  3. В режиме формы Fine Uploader перехватывает запрос отправки и отправляет файлы (файлы) и все поля формы через ajax/XHR. В настоящее время он ожидает, что будет выбран хотя бы один файл, поскольку поля формы отправляются как параметры для каждого выбранного файла. Отсутствие выбранных файлов означает, что в текущем состоянии поля формы не могут быть отправлены. Изменение этого параметра потребует корректировки внутреннего кода Fine Uploader. Вы можете обойти это, не используя режим формы. Вместо этого вам нужно будет отправить данные формы в один запрос, а затем передать Fine Uploader любым выбранным файлам через API.
  4. Точный загрузчик должен перехватить форму submit, поэтому должен быть только один ответ на файл. Поля формы отправляются с каждым файлом.
  5. Это может быть необходимый подход, если вы хотите сделать поле файла необязательным для своих пользователей.
+0

Отлично. Для №1 это то, что я понял. Для # 2 я знал о uuid для каждого файла, который я ловушку на стороне сервера. Но мне нужно будет создать uuid для полного представления формы, чтобы я не реплицировал создание нового события. Я могу понять, как это сделать. Для № 3-5 это тоже то, что я понял, поэтому мне нужно будет использовать некоторую клиентскую логику для использования Fine Uploader, когда есть файлы, а не когда нет. – paulr

+0

Основываясь на ответе Рей Ничолуса, я внесла несколько изменений в мой код: Клиент: [ссылка] (http://pastebin.com/Px3BYasv) Сервер: [ссылка] (http://pastebin.com/kzgR23Ss) У меня все еще есть одна небольшая проблема. Если пользователь выберет-then-unselects вложения, я получу файлы, чтобы выгрузить предупреждение об ошибке. Я искал и не могу найти метод destroy() для экземпляра fineuploader, и я безуспешно пытался уничтожить его с помощью кода. Было бы полезно иметь рутину, чтобы хотя бы улавливать сообщения об ошибках и уничтожать их. – paulr

Смежные вопросы