web-dev-qa-db-fra.com

Ma demande $ .ajax a cessé de fonctionner correctement sur iOS 11.3

Ce code fonctionnait très bien et rapidement pendant des années. 

Étant donné que $ .ajax ne reçoit aucune donnée de fichier, à la mise à jour vers iOS 11.3, cette $ .ajax semble fonctionner très lentement, jusqu’à 20 secondes pour soumettre un simple formulaire en texte seulement lorsqu’il est testé sur un navigateur iOS. 

Mais si l'élément de fichier transmet les données de fichier, $ .ajax fonctionne parfaitement dans les deux cas et aussi rapidement que prévu.

HTML ---
<form enctype="multipart/form-data" id="chatform" method="post">
    <input type="file" name="pic" id="pic" class="hidden" />
    <textarea name="chattextarea" id="chattextarea" rows="3" cols="10"></textarea>
    <input type="button" value="Send" onclick="sendMessage();" />
</form>

JavaScript ---
function sendMessage() {
    var formData = new FormData($("#chatform")[0]);
    $.ajax({
        url: 'send.php',
        type: 'POST',
        data: formData,
        async: true,
        cache: false,
        contentType: false,
        processData: false,
        success: function (returndata) {
            /* some success message */
        }
    });
}

Est-ce un bug iOS 11.3?

----- MODIFIER -----

Oui, en effet, il ne s’agit pas uniquement d’un bogue pour iOS 11.3, mais aussi d’un bogue pour Safari 11.1 . À ce jour, j’ai testé ces environnements et répliqué le bogue:

  1. Mac OS, Safari
  2. iOS, Safari
  3. iOS, Chrome
  4. iOS, WKWebView (application hybride)

J'ai écrit une solution de contournement simple, veuillez vérifier ma réponse et laissez-moi savoir si vous avez une solution plus propre.

11
Gordon Casper

Au lieu de la suppression, j'ai désactivé les entrées de fichier vides de formData avant la création de la classe:

if(!file.val()){
   file.attr('disabled', true);
}
3
gugun4ik

Cette fonction fonctionne sur iOS 11.3, iOS 10.2 et Windows Chrome 65.0.3325.181 . Quelqu'un peut-il aider à tester sur d'autres navigateurs?

function formDataFileFix(formData) {
    try {
        if (formData.keys) {
            var formKeysToBeRemoved = [];
            for (var key of formData.keys()) {
                var fileName = null || formData.get(key)['name'];
                var fileSize = null || formData.get(key)['size'];
                if (fileName != null && fileSize != null && fileName == '' && fileSize == 0) {
                    formKeysToBeRemoved.Push(key);
                }
            }
            for (var i = 0; i < formKeysToBeRemoved.length; i++) {
                formData.delete(formKeysToBeRemoved[i]);
            }
        }
    }
    catch(err) {
        console.log(err.message);
    }
}

var formData = new FormData($(formID)[0]);
formDataFileFix(formData);
3
Peter

Je vous remercie! J'ai combiné les deux réponses précédentes à un exemple plus propre et fonctionnel. Je pense que Apple devrait résoudre ce problème rapidement ...

    var formData = new FormData( this );

    if(!$("#image").val()) {
    formData.delete('image_file');
    }

    if(!$("#pdf").val()) {
    formData.delete('pdf_doc');
    }

    $.ajax({
    type: 'post',
    data: formData
    //and so on...
0
Bengt Barsebaeck

Supprimez simplement l'entrée de fichier vide de formData:

if(!imageUsed){
   formData.delete('file[]');
}

Nous testons toujours sur différents appareils, mais cela semble fonctionner.

0
pleqtron

J'ai eu le même problème, cela a fonctionné pour moi, j'espère que ma solution aidera n'importe qui: 

Avant la demande Ajax: 

// disable all empty inputs with type file : 

 let fileInputs = document.querySelectorAll(".myForm input[type=file]");
        fileInputs.forEach(function (file) {

            let fileInput =  $('#'+file.id);
            if(fileInput.get(0).files.length === 0){
                fileInput.attr('disabled',true);
            }

        });

Ensuite, vous effectuez ici votre demande Ajax normale.

Remarque: après cela, vous devrez peut-être réactiver vos entrées avec les fichiers de type . (De la même manière que vous les avez désactivés).

 let myFiles = document.querySelectorAll(".myForm input[type=file]");
        myFiles.forEach(function (file) {
            let fileInput =  $('#'+file.id);
            fileInput.attr('disabled',false);
        });
0
Ahmed Marzouk

J'ai exactement le même problème! J'ai une application Web avec plusieurs formulaires qui ne fonctionnent plus si l'utilisateur ne choisit PAS d'inclure un fichier. J'utilise iOS 11.3 bêta depuis la version bêta 1 et espère que chaque nouvelle version bêta résoudra ce problème. Très ennuyeux que le problème persiste dans la publication publique. Espérons qu’il y aura plus d’informations sur la façon de résoudre ce problème maintenant, alors que ce "bogue" affecte un plus grand nombre de personnes.

0
Bengt Barsebaeck

Même problème ici !!! Étant donné que beaucoup IOS utilisateurs sont en train de mettre à jour, ce sera un réel problème. Quelqu'un a-t-il trouvé une solution de contournement à ce problème? Fonctionne si j'envoie un fichier.

0
user1851673

Ma solution consiste à séparer le comportement des formulaires avec et sans fichier sélectionné.

Cette solution est assez méchante, mais elle fonctionne autour d’un bogue Apple :(

function sendMessage() {
    // Form does not have file selected
    if(!$("#pic").val()) {
        var formData = $("#chatform").serialize();
        $.post("send.php", formData, function(data) {
            /* success */
        });
    }
    // Form has file selected
    else {
        var formData = new FormData($("#chatform")[0]);
        $.ajax({
            url: 'send.php',
            type: 'POST',
            data: formData,
            async: true,
            cache: false,
            contentType: false,
            processData: false,
            success: function (data) {
                /* success */
            }
        });
    }
}

S'il vous plaît laissez-moi savoir si vous avez une solution plus propre.

0
Gordon Casper