@Hirshy 和@Luk,你的解决方案真的很优雅,而且很有魅力。文件输入字段甚至不会发送到服务器,因此很容易确定文件何时在有效负载中。
在我的 Angular 应用程序中,我有一个视图,用于添加新文档和一些相关数据,以及用于编辑数据和/或上传替换文档。
这是我的解决方案:
/*------------------------------------------------------------------------*/
/* Prepare file uploader. */
/* */
/* jQuery-File-Upload does not submit a form unless a file has been */
/* selected. To allow this, we manually add an empty file to be uploaded, */
/* which makes the submit handler available, and we replace the submit */
/* handler with one that will submit the form without a selected file. */
/* */
/* see: http://stackoverflow.com/q/21760757/2245849. */
/*------------------------------------------------------------------------*/
var uploadForm = $('#DocumentForm');
var fileInput = $('#DocumentForm input:file');
$scope.uploadOptions =
{
url: Services.Documents.uploadRoute,
autoUpload: false,
dropZone: uploadForm,
fileInput: fileInput,
replaceFileInput: false
};
/*---------------------------------------------------------------*/
/* Initialize the uploader. This must be done with the options */
/* or an error will be thrown when an empty file is added below. */
/* It is also necessary to initialize with the options here as */
/* well as in the element html or the results are unpredictable. */
/*---------------------------------------------------------------*/
uploadForm.fileupload($scope.uploadOptions);
/*--------------------------------------------------------------------*/
/* File processing is called in the default add handler and this */
/* handler is called after a successful add. It displays the file */
/* name in the drop zone, sets the document name for a new document, */
/* and sets the submit handler to submit the form with file and data. */
/* */
/* If editing a document, a dummy empty file object is manually */
/* added to make the submit handler available so the user can make */
/* data changes without uploading a new document. */
/*--------------------------------------------------------------------*/
uploadForm.bind("fileuploadprocessdone", function(e, data)
{
/*------------------------------------------------------------*/
/* Get the user selected file object and display the name. */
/* Set the document name to the file name if not already set. */
/*------------------------------------------------------------*/
if (data.files[0].name)
{
$scope.document.file = data.files[0];
if (!$scope.document.name)
$scope.document.name = $scope.document.file.name;
MessageService.clear();
}
/*--------------------------------------*/
/* If this is the dummy file add, reset */
/* 'acceptFileTypes' to global config. */
/*--------------------------------------*/
else
delete $scope.uploadOptions.acceptFileTypes;
/*------------------------------------------------------------*/
/* Set the submit handler. We have to do this every time a */
/* file is added because 'data' is not passed to the handler. */
/*------------------------------------------------------------*/
uploadForm.unbind('submit').submit(function(e)
{
e.preventDefault();
data.submit();
});
});
/*---------------------------------------------------------------------------*/
/* If we get here, the file could not be added to the process queue most */
/* likely because it is too large or not an allowed type. This is dispatched */
/* after the add event so clear the current file and show the error message. */
/*---------------------------------------------------------------------------*/
uploadForm.bind("fileuploadprocessfail", function(e, data)
{
$scope.document.file = null;
MessageService.notice(data.files[data.index].error);
});
/*-----------------------------------------------------------------*/
/* Add a dummy empty file if not a new document so the submit */
/* handler is set and the user does not have to upload a document. */
/*-----------------------------------------------------------------*/
if (!$scope.new_document)
{
$scope.uploadOptions.acceptFileTypes = null;
uploadForm.fileupload('add', { files: [{}] });
}
更新
如果服务器返回失败状态,uploadForm.fileupload('add', { files: [''] }); 将导致在浏览器中抛出异常。 JFU 尝试分配 data.files[0].error 并且 data.files[0] 不存在。
通过分配空数组而不是空字符串可以很好地解决问题:uploadForm.fileupload('add', { files: [[]] });
我已经更新了上面的例子。
2/29/16 更新
结果我确实想限制文件类型,所以我修改了我的脚本以在添加虚拟文件之前清除“acceptFileTypes”属性并在添加处理程序中重置它。还发现我无法访问添加处理程序中的进程错误,因此将其替换为“fileuploadprocessdone”并处理了“fileuploadprocessfail”中的错误。
我已经更新了上面的示例,但我们仍在使用 JFU 5.42.0。
重要
我正在使用 5.42.0,这是一个非常旧的 JFU 版本。我没有编写此代码,并且我的第一次升级尝试失败了。当我升级时,我会更新这个解决方案。**