javascript - js下载 - jquery.form.js用法




Safari 11.1:当输入[type=file]为空时,ajax/XHR表单提交失败 (4)

更新:旧答案在Firefox中不起作用。

Firefox在空文件字段(而不是其他浏览器中的File对象FormData.get()上返回FormData.get() 空字符串 。 因此,当使用旧的解决方法时,空<input type="file">将像空<input type="text"> 。 不幸的是,在创建FormData对象后,无法区分空文件和空文本。

请改用此解决方案:

var $form = $('form')
var $inputs = $('input[type="file"]:not([disabled])', $form)
$inputs.each(function(_, input) {
  if (input.files.length > 0) return
  $(input).prop('disabled', true)
})
var formData = new FormData($form[0])
$inputs.prop('disabled', false)

现场演示: https://jsfiddle.net/ypresto/05Lc45eL/https://jsfiddle.net/ypresto/05Lc45eL/

对于非jQuery环境:

var form = document.querySelector('form')
var inputs = form.querySelectorAll('input[type="file"]:not([disabled])')
inputs.forEach(function(input) {
  if (input.files.length > 0) return
  input.setAttribute('disabled', '')
})
var formData = new FormData(form)
inputs.forEach(function(input) {
  input.removeAttribute('disabled')
})

对于Rails(rails-ujs / jQuery-ujs): https://gist.github.com/ypresto/cabce63b1f4ab57247e1f836668a00a5 ://gist.github.com/ypresto/cabce63b1f4ab57247e1f836668a00a5

旧答案:

过滤FormData(在Ravichandra Adiga的回答中)更好,因为它不会操纵任何DOM。

但是根据<form>规范,FormData中的部件顺序保证与输入表单中的元素顺序相同 。 如果有人依赖此规范,它可能会导致另一个错误。

片段下方将保留FormData顺序和空白部分。

var formDataFilter = function(formData) {
    // Replace empty File with empty Blob.
  if (!(formData instanceof window.FormData)) return
  if (!formData.keys) return // unsupported browser
  var newFormData = new window.FormData()
  Array.from(formData.entries()).forEach(function(entry) {
    var value = entry[1]
    if (value instanceof window.File && value.name === '' && value.size === 0) {
      newFormData.append(entry[0], new window.Blob(), '')
    } else {
      newFormData.append(entry[0], value)
    }
  })
  return newFormData
}

现场示例如下: https://jsfiddle.net/ypresto/y6v333bq/https://jsfiddle.net/ypresto/y6v333bq/

对于Rails,请参见此处: https://github.com/rails/rails/issues/32440#issuecomment-381185380https://github.com/rails/rails/issues/32440#issuecomment-381185380

(注意:iOS 11.3的Safari有此问题,但11.2不是。)

更新 :从Webkit build r230963开始 ,此问题已在Webkit中得到解决。

===========

自从最近在macOS和iOS以及Safari Technology Preview 11.2上更新Safari 11.1以来,当input[type=file]字段没有选择input[type=file]时,我的Web应用程序中的$.ajax调用失败(不需要)在我的形式)。 当字段确实选择了文件时没有失败。

ajaxerror回调运行,Safari控制台包含以下消息: Failed to load resource: The operation couldn't be completed. Protocol error Failed to load resource: The operation couldn't be completed. Protocol error 。 我是HTTPS并通过HTTPS提交到同一域(和服务器)上的某个位置。

在11.1更新之前,当没有选择文件时, $.ajax调用提交正常。 最新版本的Chrome和Firefox没有任何问题。

我的代码的相关部分:

输入:

Browse... <input id="file-upload" type="file" name="image" accept=".jpg,.jpeg">

JS:

var formData = new FormData($(this)[0]);
$.ajax({
    type: 'POST',
    enctype: 'multipart/form-data',
    url: '../process.php',
    data: formData,
    contentType: false,
    processData: false,
    cache: false,
    success: function(response) { ... },
    error: function() { //my code reaches here }
});

作为一个临时的(希望)解决方案,我正在检测一个空文件字段并在ajax调用之前将其从formData删除,并且所有内容都按预期/之前工作:

$("input[type=file]").each(function() {
    if($(this).val() === "") {
        formData.delete($(this).attr("name"));
    }
});

我做错了什么,Safari是否存在问题,或者现在在ajax调用中是否需要考虑Safari的变化?


Webkit build r230963开始,Webkit已经解决了这个问题。 我下载并运行该构建并确认问题已解决。 不知道哪个公共版本可用于包含此修复程序的Safari。



这有助于我检查输入字段是否为空。 如果为空,请在创建FormData之前禁用输入字段。 创建FormData后,删除“已禁用”属性。 与其他答案的区别在于,我搜索“input [0] .files.length == 0”。

// get the input field with type="file"
var input = $('#myForm').find("input[type='file']")

// add the "disabled" attribute to the input
if (input[0].files.length == 0) {
  input.prop('disabled', true);
}

// create the formdata  
var formData = new FormData($(this)[0]);

// remove the "disabled" attribute
input.prop('disabled', false);




safari