web-dev-qa-db-fra.com

Dirigez un fichier téléchargé vers un serveur distant avec un noeud (idéalement avec le même nom de fichier)

Je souhaite télécharger un fichier sur mon serveur app.js, ce qui devrait le rediriger vers un serveur multi-domaines comme mon serveur upload.js.

Le code complet peut être trouvé sous le suivant link

Le serveur upload.js fonctionne. Mon problème est le serveur app.js. Request semble être capable de diffuser des fichiers en continu ( https://github.com/request/request#streaming ). Mais je ne le fais pas fonctionner. Je reçois toujours: [Erreur: protocole non valide. ] dans mon application.js.

Ce doit être cette ligne:

fs.createReadStream(file.path).pipe(request.post('localhost:4000/upload'))

J'ai changé de post pour mettre et dans mon upload.js la méthode de post aussi pour mettre, mais il en résulte la même erreur.

Mon objectif est de télécharger un fichier de la page html sur localhost: 3000/upload, qui le redirige vers localhost: 4000/upload (idéalement avec le même nom de fichier). Mais je ne le fais pas fonctionner (ceci post ne m'a pas aidé).

app.js:

var express = require('express')
    , multiparty = require('multiparty')
    , request = require('request')
    , fs = require('fs')
    , util = require('util')
    , http = require('http');

var app = express();
app.use('/static', express.static('static'));

process.on('uncaughtException', function (err) {
    console.log(err);
});

app.get('/', function (req, res) {
    res.redirect('static/index.html');
});

app.post('/upload', function(req, res, next){

    //https://github.com/request/request#streaming

    var form = new multiparty.Form();

    form.parse(req, function(err, fields, files) {
        res.writeHead(200, {'content-type': 'text/plain'});
        res.write('received upload:\n\n');
        res.end(util.inspect({fields: fields, files: files}));
    });
    form.on('file', function(name,file) {

        //stream it to localhost:4000 with same name
        fs.createReadStream(file.path).pipe(request.post('localhost:4000/upload'))

        console.log(file.path);
    });

});

var server = app.listen(3000, '0.0.0.0' ,function () {
    var Host = server.address().address;
    var port = server.address().port;

    console.log('Example app listening at http://%s:%s', Host, port);
});

index.html:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>Upload</title>
</head>
<body>
  <h2>Upload</h2>
  <form method="post" action="/upload" enctype="multipart/form-data">
    <input type="file" id="file" name="file" />
    <button>upload</button>
  </form>
</body>
</html>

upload.js:

var express = require('express')
    , multiparty = require('multiparty')
    , cors = require('cors')
    , util = require('util')
    , app = express();

app.use(cors());
process.on('uncaughtException', function (err) {
    console.log(err);
});

app.get('/', cors(), function(req, res, next){
    res.json({msg: 'This is CORS-enabled for all origins!'});
});

app.post('/upload', cors(), function(req, res, next){
    var form = new multiparty.Form();

    form.parse(req, function(err, fields, files) {
        res.writeHead(200, {'content-type': 'text/plain'});
        res.write('received upload:\n\n');
        res.end(util.inspect({fields: fields, files: files}));
    });
    form.on('file', function(name,file) {
        console.log(file);
        console.log(name);
    });

});

app.listen(4000, function(){
    console.log('CORS-enabled web server listening on port 4000');
});
8
svenhornberg

Mise à jour

Je crois que vous manquez le protocole de l'URL. Cela devrait fonctionner si vous ajoutez le protocole http à l'URL:

fs.createReadStream(file.path).pipe(request.post('http://localhost:4000/upload'))

Faire en sorte que le téléchargement fonctionne

Lorsque vous dirigez le contenu du fichier vers la fonction POST dans upload.js, les données du formulaire multipart sont perdues. Vous devez créer une nouvelle demande POST et transmettre le contenu du fichier d'origine.

Procédez comme suit dans app.js:

 form.on('file', function(name, file) {

    var formData = {
      file: {
        value:  fs.createReadStream(file.path),
        options: {
          filename: file.originalFilename
        }
      }
    };

    // Post the file to the upload server
    request.post({url: 'http://localhost:4000/upload', formData: formData});
}

Cela transmettra également le nom de fichier d'origine. Pour plus d'informations, voir: https://github.com/request/request#multipartform-data-multipart-form-uploads

3
kmandov

J'avais un problème similaire mais je voulais diffuser le fichier directement sur le serveur distant au lieu de le sauvegarder localement. Voici mes modifications pour que le streaming fonctionne correctement:

app.post('/upload', function(request, response, next) {
    var form = new multiparty.Form();

    form.on('part', function(formPart) {
        var contentType = formPart.headers['content-type'];

        var formData = {
            file: {
                value: formPart,
                options: {
                    filename: formPart.filename,
                    contentType: contentType,
                    knownLength: formPart.byteCount
                }
            }
        };

        requestJs.post({
            url: 'http://localhost:4000/upload',
            formData: formData,

            // These may or may not be necessary for your server:
            preambleCRLF: true,
            postambleCRLF: true
        });
    });

    form.on('error', function(error) {
        next(error);
    });

    form.on('close', function() {
       response.send('received upload');
    });

    form.parse(request);
});
5
jameslk

Vous pouvez réellement utiliser stream.pipe(request.post(url));, puis sur un autre serveur, votre variable req aura un comportement de type flux, vous devriez donc pouvoir req.pipe(fs.createWriteStream(path));.

Utilisez req.params sur votre itinéraire pour conserver le nom de fichier.

Exemple de code pour le serveur numéro un (utilisez un hachage tel que md5 pour valider votre demande):

const stream = fs.createReadStream(path);

const md5 = crypto.createHash('md5')
    .update(`${filename}${secret}`)
    .digest('hex').toUpperCase();

const url = `http://${Host}/upload/${md5}/${filename}`;

const r = request.post(url, (err, resp, body) => {});

stream.pipe(r);

Exemple de code pour le serveur deux:

router.post('/upload/:md5/:filename', function(req, res, next) {
    const { md5, filename } = req.params;

    const check = crypto.createHash('md5')
        .update(`${filename}${secret}`)
        .digest('hex').toUpperCase();

    if (md5 !== check) {
        res.writeHead(403);
        res.end('403');
        return;
    }

    req.pipe(fs.createWriteStream(filename));

    req.on('end', next);
});
0
HydraOrc