Node-red file repository

De knowledge
Version datée du 11 juillet 2026 à 16:00 par Jpinon (discussion | contributions) (Page créée avec « = MegaUpload personnel avec Node-RED = == Objectif == Mettre en place un petit service de partage de fichiers : * Upload protégé par login/mot de passe. * Téléchargement public via une URL. * Noms des fichiers pseudonymisés. * Fichiers servis directement par Node-RED. * Reverse proxy HTTPS assuré par Caddy. Architecture : <pre> Internet | v Front-Router (Caddy) | v Node-RED (main-host) | +--- Upload via flow Node-RED | +-... »)
(diff) ← Version précédente | Version actuelle (diff) | Version suivante → (diff)
Aller à la navigation Aller à la recherche

MegaUpload personnel avec Node-RED

Objectif

Mettre en place un petit service de partage de fichiers :

  • Upload protégé par login/mot de passe.
  • Téléchargement public via une URL.
  • Noms des fichiers pseudonymisés.
  • Fichiers servis directement par Node-RED.
  • Reverse proxy HTTPS assuré par Caddy.

Architecture :

Internet
    |
    v
Front-Router (Caddy)
    |
    v
Node-RED (main-host)
    |
    +--- Upload via flow Node-RED
    |
    +--- Fichiers statiques (/var/www/static-files)

Installation des modules

Installer :

node-red-contrib-http-multipart
@alexandrainst/node-red-http-basic-auth

Le premier permet de recevoir des formulaires HTML multipart/form-data.

Le second ajoute une authentification HTTP Basic.

Répertoire de stockage

Créer un répertoire destiné à contenir les fichiers :

sudo mkdir -p /var/www/static-files
sudo chown nodered:nodered /var/www/static-files

Adapter l'utilisateur si nécessaire.

Activation du serveur statique Node-RED

Modifier :

~/.node-red/settings.js

Décommenter et adapter :

httpStatic: [
    {
        path: "/var/www/static-files",
        root: "/files/"
    }
],

Redémarrer Node-RED :

systemctl --user restart nodered

Ou selon l'installation :

sudo systemctl restart nodered

Test :

echo hello > /var/www/static-files/test.txt

Puis ouvrir :

https://node-red.mon-domaine.fr/files/test.txt

Si le texte "hello" apparaît, le serveur statique fonctionne.

Page d'upload

URL :

https://node-red.mon-domaine.fr/megaupload/

HTML :

<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>MegaUpload</title>

<style>
body {
    font-family: Arial, Helvetica, sans-serif;
    background: #f4f7fb;
}

.container {
    max-width: 700px;
    margin: 80px auto;
    background: white;
    padding: 40px;
    border-radius: 16px;
    box-shadow: 0 10px 30px rgba(0,0,0,0.1);
}

h1 {
    text-align: center;
}

.upload-box {
    text-align: center;
}

button {
    background: #2563eb;
    color: white;
    border: 0;
    padding: 12px 30px;
    border-radius: 8px;
    cursor: pointer;
}
</style>
</head>

<body>

<div class="container">

<h1>📤 MegaUpload</h1>

<div class="upload-box">

pload/upload"
      method="post"
      enctype="multipart/form-data">

    <input type="file"
           name="fichier"
           required>

    <button type="submit">
        Envoyer le fichier
    </button>

</form>

</div>

</div>

</body>
</html>

Protection par mot de passe

Ajouter un noeud :

http basic auth

devant :

  • GET /megaupload/
  • POST /megaupload/upload

Ainsi :

[http in]
      |
      v
[http basic auth]
      |
      v
[template]
      |
      v
[http response]

Utilisateur unique

Configurer directement :

Utilisateur : upload
Mot de passe : xxxx

Fichier d'utilisateurs

Format :

jean:motdepasse
alice:motdepasse

Ou mieux, avec mots de passe bcrypt.

Exemple :

jean:$2y$10$...
alice:$2y$10$...

Réception du fichier

Flow :

[httpInMultipart]
        |
        v
[http basic auth]
        |
        v
[function]
        |
        v
[exec]
        |
        v
[template]
        |
        v
[http response]

Configuration HTTP Multipart :

[
  {
    "name": "fichier",
    "maxCount": 1
  }
]

Pseudonymisation du nom de fichier

Function :

const f = msg.req.files.fichier[0];

// Extension
const pos = f.originalname.lastIndexOf(".");
const ext = (pos >= 0)
    ? f.originalname.substring(pos).toLowerCase()
    : "";

// Identifiant unique
const id =
    Date.now().toString(36) +
    "-" +
    Math.random().toString(36).substring(2, 10);

// Nom stocké
msg.safeName = id + ext;

// Nom affiché
msg.nomFichier =
    f.originalname.replace(/[<>]/g, "");

// URL publique
msg.urlFichier =
    "https://node-red.mon-domaine.fr/files/" +
    encodeURIComponent(msg.safeName);

// Déplacement du fichier
msg.payload =
    '-c \'mv "' + f.path +
    '" "/var/www/static-files/' +
    msg.safeName + '"\'';

return msg;

Exemple :

PhotoVacances.jpg

devient :

mrggesvw-hwdhacrc.jpg

Déplacement du fichier

Noeud Exec :

Command : bash
Append : msg.payload

Le fichier temporaire créé par Multipart est déplacé :

/tmp/abc123
        ->
/var/www/static-files/mrggesvw-hwdhacrc.jpg

Page de succès

Template :

<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Fichier enregistré</title>

<style>
body {
    font-family: Arial, Helvetica, sans-serif;
    background: #f4f7fb;
}

.container {
    max-width: 800px;
    margin: 80px auto;
    background: white;
    padding: 40px;
    border-radius: 16px;
    box-shadow: 0 10px 30px rgba(0,0,0,0.1);
}

.linkbox {
    padding: 15px;
    background: #f8fafc;
    border-radius: 8px;
}

button {
    background: #2563eb;
    color: white;
    border: 0;
    padding: 10px 20px;
    border-radius: 8px;
}
</style>

<script>
function copyLink() {
    const text =
        document.getElementById("downloadLink").value;

    navigator.clipboard.writeText(text);

    document.getElementById("status").innerText =
        "Lien copié ✓";
}
</script>

</head>
<body>

<div class="container">

<h1>✅ Fichier enregistré</h1>

<p>
Nom du fichier :
<b>{{nomFichier}}</b>
</p>

<div class="linkbox">
    <input id="downloadLink"
           type="text"
           value="{{urlFichier}}"
           readonly
           style="width:100%">
</div>

<br>

<button onclick="copyLink()">
    Copier le lien
</button>

<span id="status"></span>

</div>

</body>
</html>

Utilisation

Upload

L'utilisateur authentifié ouvre :

https://node-red.mon-domaine.fr/megaupload/

Sélectionne un fichier puis clique :

Envoyer le fichier

Téléchargement

Le destinataire reçoit un lien :

https://node-red.mon-domaine.fr/files/mrggesvw-hwdhacrc.jpg

Aucune authentification n'est nécessaire.

Améliorations possibles

  • Limiter la taille maximale des fichiers.
  • Limiter les extensions autorisées.
  • Suppression automatique après X jours.
  • Historique des uploads dans MariaDB.
  • Génération de liens à durée de vie limitée.
  • Statistiques de téléchargement.
  • QR-Code du lien de téléchargement.

Résultat

On obtient un mini "WeTransfer" personnel :

  • HTTPS via Caddy.
  • Upload privé.
  • Download public.
  • Noms de fichiers non prévisibles.
  • Aucun serveur web supplémentaire requis.
  • Entièrement réalisé avec Node-RED.