Node-red file repository
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.
Architecture :
Internet
|
v
Reverse Proxy
|
v
Node-RED (main-host)
|
+--- Upload via flow Node-RED
|
+--- Fichiers statiques (/var/www/static-files)
Installation des modules
Copilot m'avait proposer d'Installer "à ma main" :
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.
Pour le coup l'interface graphique de node-red le permet tout aussi bien.
Dans le menu en haut a droite on a l'option "Gérer la palette". On a l'impression que c'est juste de la GUI mais non on passe par là pour ajouter des modules.
On clique sur "Gérer la palette" et on a une fenêtre de sélection.
On choisit l'onglet "Installer" et on recherche node-red-contrib-http-multipart.
Dans le screenshot ci-dessus le bouton "Installé" est grisé mais si le module n'était pas installé on aurait un bouton installer. Il suffit de cliquer dessus et c'est fait.
Répertoire de stockage
Créer un répertoire destiné à contenir les fichiers :
sudo mkdir -p /var/www/static-files/ sudo mkdir -p /var/www/static-files/assets sudo chown nodered:nodered /var/www/static-files/assets
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/assets",
root: "/files/"
}
],
Redémarrer Node-RED :
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>
Que l'on rangera dans /var/www/static-files/upload.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
Je penses que c'est la seule solution acceptable car les mots de passes ne sont pas "en clair"
Format :
jean:motdepasse alice:motdepasse
Ou mieux, avec mots de passe bcrypt.
Exemple :
jean:$2y$10$... alice:$2y$10$...
J'ai donc crée la chaine de noeuds:
C'est tres simple :
- Ou expose l'url /megaupload (noeud index)
- au authentifie l'utilisateur
- on lit le fichier /var/www/static-files/upload.html
- On le renvoie au client
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
}
]En effet, dans la page d'upload on ne propose qu'un seul fichier. SI on veut en envoyer plusieurs, soit on refait l'opération soit un fait un zip ou un tgz.
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, par exemple :
mrggesvw-hwdhacrc.jpg
Déplacement du fichier
Noeud Exec :
On lance l'exécution du msg.payload construit au dessus.
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>
Récapitulatifs des actions ci-dessus.
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 le reverse proxy.
- Upload privé.
- Download public.
- Noms de fichiers non prévisibles.
- Aucun serveur web supplémentaire requis.
- Entièrement réalisé avec Node-RED.