首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Safari11.1:当输入[type=file]为空时,ajax/XHR表单提交失败

Safari11.1:当输入[type=file]为空时,ajax/XHR表单提交失败
EN

Stack Overflow用户
提问于 2018-04-02 23:32:31
回答 6查看 11.8K关注 0票数 40

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

===========

自从最近在macOS和iOS上更新Safari11.1,以及在Safari Technology Preview 11.2中,当input[type=file]字段没有选择文件时,我的web应用程序中的$.ajax调用就会失败(这在我的表单中不是必需的)。如果字段确实选择了文件,则不会失败。

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

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

我的代码的相关部分:

输入:

代码语言:javascript
复制
Browse... <input id="file-upload" type="file" name="image" accept=".jpg,.jpeg">

JS:

代码语言:javascript
复制
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中删除,一切都按预期/之前进行:

代码语言:javascript
复制
$("input[type=file]").each(function() {
    if($(this).val() === "") {
        formData.delete($(this).attr("name"));
    }
});

我是不是做错了什么,是Safari有问题,还是Safari的变化需要在ajax调用中解决?

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2018-04-25 03:09:44

Webkit build r230963开始,这个问题已经在Webkit中得到了解决。我下载并运行了该构建,并确认问题已解决。不知道何时才能为包含此修复的Safari提供公开版本。

票数 5
EN

Stack Overflow用户

发布于 2018-04-14 10:55:45

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

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

请改用此解决方案:

代码语言:javascript
复制
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环境:

代码语言:javascript
复制
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>规范。如果有人依赖此规范,可能会导致另一个bug。

下面的代码片段将保持FormData顺序和空部分。

代码语言:javascript
复制
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没有。)

票数 18
EN

Stack Overflow用户

发布于 2018-04-07 23:33:47

为了解决这个问题,我使用jQuery remove()方法从DOM中完全删除了输入类型文件。

代码语言:javascript
复制
$("input[type=file]").each(function() {
    if($(this).val() === "") {
        $(this).remove();
    }
});
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49614091

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档