javascript - Safari 11.1 : ajax/XHR form submission fails when input[type=file] is empty

标签 javascript jquery ajax forms safari

更新:截至 Webkit build r230963 , 这个问题已经在 Webkit 中解决了。

===========

自从最近在 macOS 和 iOS 上更新 Safari 11.1 以及 Safari Technology Preview 11.2 以来,当 input[type= file] 字段没有选择文件(我的表单不需要)。当字段确实选择了文件时没有失败。

ajaxerror 回调运行,Safari 控制台包含以下消息:加载资源失败:操作无法完成。协议(protocol)错误。我使用 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 是否有问题,或者 Safari 是否有变化需要在 ajax 调用中考虑?

最佳答案

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

Firefox 为 FormData.get() 返回空字符串在空文件字段上(而不是其他浏览器中的 File 对象)。所以当使用旧的解决方法时,清空 <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/

对于非 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


旧答案:

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

但是the order of parts in FormData is guaranteed to be the same order to input elements in form , 根据 <form>规范。如果有人依赖此规范,它可能会导致另一个错误。

下面的代码片段将保持 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/

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

(注意:iOS 11.3 的 Safari 有这个问题,但 11.2 没有。)

关于javascript - Safari 11.1 : ajax/XHR form submission fails when input[type=file] is empty,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49614091/

相关文章:

jquery - Laravel 4 CSRF表单通过Ajax调用提交

javascript - 无法使用 jQuery 选择器在 IE8 中选择 HTML5 元素的子元素

javascript - 如何在ajax请求成功回调中获取自动parseJSON数据?

javascript - JQuery 选项卡 : How to display a 'Loading...' message' on waiting an AJAX HTTP request response?

javascript - 创建 js 对象时,为什么不能在另一个定义的函数中使用一个定义的函数?

javascript - 一次删除多个 Div 元素 -- JavaScript

javascript - 更改默认的 Google Maps Api 默认缩放控件图像?

javascript - CSS3 从新位置的 Angular 过渡

javascript - XHR 不适合聊天应用程序?

javascript - 一页上多个表单,使用ajax发布数据,指定所选表单中的哪些输入字段