source

Safari 11.1: ajax/X입력[type=file]이(가) 비어 있으면 HR 양식 제출이 실패함

nicesource 2023. 3. 20. 23:20
반응형

Safari 11.1: ajax/X입력[type=file]이(가) 비어 있으면 HR 양식 제출이 실패함

업데이트: Webkit 빌드 r230963 현재 이 문제는 Webkit에서 해결되었습니다.

===========

MacOS 및 iOS 및 Safari Technology Preview 11.2의 최신 Safari 11.1 업데이트 이후$.ajax웹 어플리케이션의 콜이 실패했을 때input[type=file]선택한 파일이 없습니다(내 양식에는 필요 없음).필드에 파일이 선택되어 있는 경우 오류는 발생하지 않습니다.

error의 콜백.ajax가 실행되고 Safari 콘솔에 다음 메시지가 표시됩니다.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 }
});

임시(바람직한) 솔루션으로서 빈 파일필드를 검출하여 에서 삭제합니다.formData이 되기 전에ajax모든 것이 예상대로/전에는 정상적으로 동작합니다.

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

제가 잘못하고 있는 건가요, Safari에 문제가 있나요, 아니면 Safari에서 현재 해결해야 할 변경 사항이 있나요?

업데이트: 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')
})

레일(레일-ujs/j)의 경우Query-ujs):https://gist.github.com/ypresto/cabce63b1f4ab57247e1f836668a00a5


오래된 답변:

FormData 필터링(Ravichandra Adiga의 답변)은 DOM을 조작하지 않기 때문에 더 좋습니다.

그러나 FormData의 부품 순서는 폼에서 요소를 입력하는 순서와 동일함을 보증합니다.<form>사양.이 사양에 의존하는 경우 다른 버그가 발생할 수 있습니다.

다음 스니펫은 Form Data 순서와 빈 부분을 유지합니다.

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에서는 발생하지 않습니다.)

회피책으로 jQuery remove() 메서드를 사용하여 입력 유형 파일을 DOM에서 완전히 삭제합니다.

$("input[type=file]").each(function() {
    if($(this).val() === "") {
        $(this).remove();
    }
});

Webkit 빌드 r230963 현재 이 문제는 Webkit에서 해결되었습니다.그 빌드를 다운로드하여 실행한 결과 문제가 해결되었음을 확인했습니다.이 수정 프로그램이 포함된 Safari의 공개 릴리스가 언제 제공될지는 알 수 없습니다.

Perl 프로그램에서 동일한 문제로 보이는 작업을 수행했습니다.

Perl에서 멀티파트/폼 데이터를 처리하면 폼 파일 요소가 비어 있는 경우 Apple 디바이스에서 Apache 오류가 발생합니다.

회피책은 폼 데이터를 할당하기 전에 폼 요소를 삭제하는 것입니다.

$('#myForm').find("input[type='file']").each(function(){
    if ($(this).get(0).files.length === 0) {$(this).remove();}
});
var fData = new FormData($('#myForm')[0]);
...
    var fileNames = formData.getAll("filename[]");
    formData.delete("filename[]");
    jQuery.each(fileNames, function (key, fileNameObject) {
        if (fileNameObject.name) {
            formData.append("filename[]", fileNameObject);
        }
    });

이거 먹어봐!!

입력 필드가 비어 있는지 확인할 수 있습니다.비어 있는 경우 FormData를 작성하기 전에 입력 필드를 비활성화합니다.FormData를 작성한 후 "disabled" 속성을 삭제합니다.다른 답변과 다른 점은 "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);

언급URL : https://stackoverflow.com/questions/49614091/safari-11-1-ajax-xhr-form-submission-fails-when-inputtype-file-is-empty

반응형