web-dev-qa-db-fra.com

Déterminer si la chaîne est en base64 à l'aide de JavaScript

J'utilise la fonction window.atob('string') pour décoder une chaîne de base64 en chaîne. Maintenant, je me demande, existe-t-il un moyen de vérifier que la "chaîne" est réellement valide en base64? Je voudrais être averti si la chaîne n'est pas base64 afin que je puisse effectuer une action différente.

26
Jonatan

Si "valide" signifie "ne contient que des caractères base64", vérifiez par [A-Za-z0-9+/=].

Si "valide" signifie une chaîne codée en base64 "légale", vous devez vérifier la = à la fin.

Si "valide" signifie que c'est quelque chose de raisonnable après le décodage, cela nécessite une connaissance du domaine.

16
Dave Newton

Si vous voulez vérifier s'il peut être décodé ou non, vous pouvez simplement essayer de le décoder et voir s'il a échoué:

try {
    window.atob(str);
} catch(e) {
    // something failed

    // if you want to be specific and only catch the error which means
    // the base 64 was invalid, then check for 'e.code === 5'.
    // (because 'DOMException.INVALID_CHARACTER_ERR === 5')
}
45
pimvdb

Cela devrait faire l'affaire.

function isBase64(str) {
    if (str ==='' || str.trim() ===''){ return false; }
    try {
        return btoa(atob(str)) == str;
    } catch (err) {
        return false;
    }
}
23
Dan Smith

S'appuyant sur la réponse de @ atornblad, l'utilisation de l'expression régulière pour effectuer un test vrai/faux simple pour la validité de base64 est aussi simple que suit:

var base64regex = /^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/;

base64regex.test("SomeStringObviouslyNotBase64Encoded...");             // FALSE
base64regex.test("U29tZVN0cmluZ09idmlvdXNseU5vdEJhc2U2NEVuY29kZWQ=");   // TRUE
18
Philzen

J'utiliserais une expression régulière pour cela. Essaye celui-là:

/^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/

Explication:

^                          # Start of input
([0-9a-zA-Z+/]{4})*        # Groups of 4 valid characters decode
                           # to 24 bits of data for each group
(                          # Either ending with:
    ([0-9a-zA-Z+/]{2}==)   # two valid characters followed by ==
    |                      # , or
    ([0-9a-zA-Z+/]{3}=)    # three valid characters followed by =
)?                         # , or nothing
$                          # End of input
16
Anders Tornblad

Voici comment cela se fait dans l'une de mes bibliothèques de validation préférées:

const notBase64 = /[^A-Z0-9+\/=]/i;

export default function isBase64(str) {
  assertString(str); // remove this line and make sure you pass in a string
  const len = str.length;
  if (!len || len % 4 !== 0 || notBase64.test(str)) {
    return false;
  }
  const firstPaddingChar = str.indexOf('=');
  return firstPaddingChar === -1 ||
    firstPaddingChar === len - 1 ||
    (firstPaddingChar === len - 2 && str[len - 1] === '=');
}

https://github.com/chriso/validator.js/blob/master/src/lib/isBase64.js

2
Lukas

Cette méthode tente de décoder puis de coder et de comparer à l'original. Peut également être combiné avec les autres réponses pour les environnements générant des erreurs d'analyse. Il est également possible d'avoir une chaîne qui ressemble à une base64 valide d'un point de vue regex mais qui n'est pas une base64 réelle.

if(btoa(atob(str))==str){
  //...
}
2
purplelizard

Comme il y a principalement deux possibilités affichées ici (regex vs try catch), j'ai comparé les performances des deux: https://jsperf.com/base64-check/

La solution Regex semble être un gagnant beaucoup plus rapide et clair. Je ne sais pas si le regex attrape tous les cas, mais pour mes tests, cela a fonctionné parfaitement.

Merci à @Philzen pour l'expression régulière!

p.s.

Dans le cas où quelqu'un est intéressé à trouver le moyen le plus rapide de décoder en toute sécurité une chaîne base64 (c'est comme ça que je suis venu ici): https://jsperf.com/base64-decoding-check

1
Kai