Je développe un programme qui télécharge le logo ou l'image de l'utilisateur. Pour ce faire, je crée d'abord une signature côté serveur, puis je télécharge l'image du client vers cloudinary, avec cette signature.

Le problème est que j'obtiens toujours l'erreur suivante: `Signature invalide" b4000077c554448649396c31750e27141820693c ". Chaîne à signer - 'source = uw & timestamp = 1598531294 & upload_preset = signed-preset'.`` (avec une signature et un horodatage ofc différents)

J'ai suivi le guide sur leurs documents: https://cloudinary.com/documentation/upload_images#generating_authentication_signatures Mais sans aide,

Voici le code côté client:

 let signature = '';
    let timestamp = '';

    let generateSignature = function (callback, params_to_sign) {
        $.ajax({
            url: "/business/create-cloudinary-signature",
            type: "GET",
            dataType: "text",
            data: { data: params_to_sign },
            complete: function () { console.log("complete") },
            success: function (response, textStatus, xhr) {
                const res = JSON.parse(response);
                console.log(res.signature)
                signature = res.signature;
                timestamp = res.timestamp;
                console.log(signature, timestamp);
                callback(signature);
            },
            error: function (xhr, status, error) { console.log(xhr, status, error); }
        });
    }

    console.log(signature, timestamp) //correct values

    const uploadSettings = {
        apiKey: "816773373496447",
        cropping: true,
        cloudName: 'rav-chesed',
        uploadPreset: 'signed-preset'

    }

    var myWidget = cloudinary.createUploadWidget({ ...uploadSettings, uploadSignature: generateSignature, uploadSignatureTimestamp: timestamp }, (error, result) => {
        if (error) {
            console.log(error)
        }
        if (!error && result && result.event === "success") {
            console.log('Done! Here is the image info: ', result.info);
        }
    }
    )
    document.getElementById("logoUploader").addEventListener("click", function () {
        myWidget.open();
    }, false);   
    

Et voici le code côté serveur (nodejs)

router.get("/create-cloudinary-signature", (req, res) => {
  console.log("heyy");
  console.log(req.query);
  const data = req.query.data;

  // // Get the timestamp in seconds
  // var timestamp = Math.round(new Date().getTime() / 1000);
  // console.log(timestamp);
  data.timestamp = Number(data.timestamp);
  // console.log(data);

  // // Show the timestamp
  // console.log("Timestamp:", timestamp);
  // const sts = `source=${data.source}&timestamp=${data.timestamp}&upload_preset=${data.upload_preset}`;
  // console.log(sts);

  // function sortObjKeysAlphabetically(obj) {
  //   var ordered = {};
  //   Object.keys(obj)
  //     .sort()
  //     .forEach(function (key) {
  //       ordered[key] = obj[key];
  //     });
  //   return ordered;
  // }

  // var sortedObj = sortObjKeysAlphabetically(data);
  // console.log(sortedObj);
  // params_to_sign via string
  var params_to_sign =
    "source=" +
    data.source +
    "&timestamp=" +
    data.timestamp +
    "&upload_preset=" +
    data.upload_preset;
  console.log(params_to_sign);

  // Get the signature using the Node.js SDK method api_sign_request
  var signature = cloudinary.utils.api_sign_request(
    params_to_sign,
    process.env.CLOUDINARY_API_SECRET
  );
  console.log(signature);
  res.json({ signature, timestamp: data.timestamp });
});

J'obtiens les données correctement, je renvoie même un hachage au client, mais pour une raison quelconque, la signature n'est pas valide et je ne peux pas télécharger l'image.

J'apprécierais de l'aide sur celui-ci. Merci d'avance.

0
Mendi Sterenfeld 27 août 2020 à 18:40

2 réponses

Meilleure réponse

Après avoir été pendant des heures avec leur soutien, je pense que je l'ai compris par moi-même,

Il semble que le code qui génère la signature n'est pas compatible avec la version que j'ai utilisée. Sur leur documentation, ils demandent à utiliser var cloudinary = require("cloudinary").v2; Mais après l'avoir changé en var cloudinary = require("cloudinary");, tout a commencé à bien fonctionner.

J'ai également apporté quelques modifications au code: Côté serveur:

router.get("/create-cloudinary-signature", (req, res) => {
  console.log("heyy");
  //console.log(req.query);
  const data = req.query.data;
  console.log(data);
  const timeStampSignature = Math.round(new Date() / 1000);
  console.log(timeStampSignature);


  // Get the signature using the Node.js SDK method api_sign_request
  var signature = cloudinary.utils.api_sign_request(
    data,
    process.env.CLOUDINARY_API_SECRET
  );
  console.log(signature);
  res.json({ signature: signature, timestampSignature: timeStampSignature });
});

Et côté client:

<script type="text/javascript">
    let signature = '';
    let timestampSignature = '';

    let generateSignature = function (callback, params_to_sign) {
        $.ajax({
            url: "/business/create-cloudinary-signature",
            type: "GET",
            dataType: "text",
            //params _to_sign contains timestamp
            data: { data: params_to_sign },
            complete: function () { console.log("complete") },
            success: function (response, textStatus, xhr) {
                const res = JSON.parse(response);
                //console.log(res.signature)
                signature = res.signature;
                timestampSignature = res.timestampSignature;
                console.log(signature, timestampSignature);

                callback(signature);
            },
            error: function (xhr, status, error) { console.log(xhr, status, error); }
        });
    }

    const uploadSettings = {
        apiKey: "blabla",
        cropping: true,
        cloudName: 'name',
        uploadPreset: 'signed-preset'
    }

    var myWidget = cloudinary.createUploadWidget({ ...uploadSettings, uploadSignature: generateSignature, uploadSignatureTimestamp: timestampSignature }, (error, result) => {
        if (error) {
            console.log(error)
        }
        if (!error && result && result.event === "success") {
            console.log('Done! Here is the image info: ', result.info);
        }
    }
    )
    document.getElementById("logoUploader").addEventListener("click", function () {
        myWidget.open();
    }, false);
</script>
0
Mendi Sterenfeld 28 août 2020 à 15:03

La fonction api_sign_request prend un hachage (objet) et la chaîne secrète de l'API. Dans ce cas, vous fournissez une chaîne (params_to_sign) comme premier paramètre.

Ce que vous pouvez faire est de passer le data directement comme premier paramètre à api_sign_request sans aucune modification. Cela contiendra tous les paramètres nécessaires et correspondra exactement à ce que le widget de téléchargement frontal envoie.

1
Aleksandar Kostadinov 27 août 2020 à 16:02