3

我正在使用罰款上傳(v5.0.1)與jQuery,jQuery.validate和jQuery.form插件的多字段形式的新事件,可以有零到兩個文件附件。精細上傳與表單選項問題

我有它的工作,但我有幾個問題之前,我走得更遠。

  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

你可能要修剪你的問題降低到最小的可重複的例子。 – 2014-12-05 22:34:57

+0

它不可重現?這就是爲什麼我提供了工作表單的鏈接。 – paulr 2014-12-05 22:45:20

+1

您的代碼示例都不適合堆棧溢出的堆棧片段工具,尤其是第二個。它們都不是真正可執行的,也不是必須的。我通常建議人們忘記存在堆棧片段,因爲它們很少合適,並且無論如何都存在堆棧溢出(例如jsbin)之外的更好的替代方案。 – 2014-12-06 02:09:11

回答

2

回答您的問題依次是:

  1. Fine Uploader在單獨的請求中發送每個文件,並且無法更改此文件。
  2. Fine Uploader已經爲每個文件生成一個唯一的ID(UUID)。該ID與上傳請求一起發送。如果您想發送文件的其他數據,可以通過setParams API method來完成。這將隨文件一起發送您選擇的其他自定義參數。您可以爲所有文件或特定文件指定新的參數。
  3. 在表單模式下,Fine Uploader攔截提交請求並通過ajax/XHR發送文件和所有表單字段。目前,它期望至少選擇一個文件,因爲表單字段作爲每個選定文件的參數發送。缺少選定的文件意味着,在當前狀態下,表單字段無法發送。更改此操作需要調整Fine Uploader的內部代碼。你可以通過不使用表單模式來解決這個問題。相反,您需要在一個請求中提交表單數據,然後讓Fine Uploader通過API發送任何選定的文件。
  4. Fine Uploader應攔截表單提交,因此每個文件只能有一個響應。表單域與每個文件一起發送。
  5. 如果您想讓文件字段對用戶可選,這可能是必需的方法。
+0

完美。對於#1,這是我的想法。對於#2,我意識到每個文件的uuid,我在服務器端捕獲這些文件。但是,我需要爲整個表單提交創建一個uuid,以便我不復制創建新事件。我可以弄清楚如何做到這一點。對於#3-5,這也是我的想法,所以我需要在有文件時使用Fine Uploader,而不是在沒有時使用Fine-Uploader。 – paulr 2014-12-06 03:15:39

+0

基於光線Nicholus的回答,我做了一些改動,以我的代碼: 客戶:[鏈接](http://pastebin.com/Px3BYasv) 服務器:[鏈接](http://pastebin.com/kzgR23Ss) 我還有一個小問題。如果用戶選擇然後取消選擇附件複選框,我會得到沒有文件來上傳錯誤警報。我查找並找不到fineuploader實例的destroy()方法,並且我嘗試使用代碼將其銷燬失敗。有一個例程至少可以捕獲錯誤信息並將其銷燬,這將會很有幫助。 – paulr 2014-12-07 01:08:51