【发布时间】:2014-12-05 22:05:43
【问题描述】:
我正在使用带有 jQuery、jQuery.validate 和 jQuery.form 插件的 Fine Uploader (v5.0.1) 用于新事件的多字段表单,可以有零到两个文件附件。
我已经成功了,但在继续之前我有几个问题。
- 我的客户端代码为每个文件(包括其他表单元素)生成一个 POST 请求,以及仅针对其他表单元素的一个额外 POST 请求。所以,如果我的表单有两个文件附件,我会收到三个 POST 请求。这是正常行为吗?我可以在一个 POST 请求中获取所有内容吗?
- 如果多个 POST 请求是正常行为,我将不得不在第一个 POST 请求之前在客户端生成某种唯一标识符,这样我可以避免数据库中的事件记录重复并将每个文件上传与正确的事件。如果这是我需要走的方向,我可以看看这种类型的实现示例吗?
- 如果没有附加文件,我会收到一个警告对话框:“没有要上传的文件。”表单可以不带文件附件提交,所以我不想暗示用户他/她必须附加文件。我怎样才能摆脱这个对话框?
- 我目前收到一个针对表单数据的 POST 响应,以及针对每个上传的文件的一个 POST 响应。有没有办法只处理最终的 POST 响应(例如 form.onAllComplete)?如果表单没有文件附件怎么办?
- 我正在为表单使用一个服务器端点,包括文件上传。我是否应该使用两个单独的端点,一个用于其他表单字段,一个用于文件上传?
这是我的表格: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);
?>
【问题讨论】:
-
您可能希望将您的问题精简为一个最小的可重现示例。
-
不可重现?这就是我提供工作表单链接的原因。
-
您的代码示例都不是堆栈溢出的堆栈 sn-ps 工具的良好候选者,尤其是第二个。两者都不是真正可执行的,也不需要是。我通常建议人们忘记堆栈 sn-ps 的存在,因为它们很少适用,并且无论如何存在堆栈溢出之外更好的替代方案(例如 jsbin)。
-
是的,我不确定要为代码 sn-ps 使用哪个工具。这就是为什么我在 Firebug 中添加了一个工作表单的链接。
标签: php jquery jquery-validate fine-uploader jquery-forms-plugin