Использование Express для получения фрагментов данных JSON и вставки в PostgreSQL - PullRequest
0 голосов
/ 22 февраля 2020

Я хотел бы сделать краткое введение, прежде чем задавать мой вопрос.

Приведенный ниже пример отлично работает для чтения файла размером 400 МБ JSON в виде потока и добавления данных в базу данных PostgreSQL.

var fs = require('fs')
var JSONStream = require('JSONStream')
var es = require('event-stream')
var Pool = require('pg').Pool

var pool = new Pool({user: user, host: host, database: database, password: password, port: port})
var types = require('pg').types
types.setTypeParser(1114, str => str)

var getStream = function () {
    var jsond = 'export.json', //400MB File
        stream = fs.createReadStream(jsond, {encoding: 'utf8'}),
        parser = JSONStream.parse('*');
        return stream.pipe(parser);
};

var i = 0
getStream().pipe(es.mapSync(function (d){
    pool.query(`INSERT INTO metrics ("id","test") values ($1,$2)`,[d.id,d.test]).catch(console.error).then(function(){
        console.log('Inserted...', i++)
    })
}));

Я использую приведенный ниже код, чтобы получить файл JSON из формы загрузки, используя express и express -fileupload. Он также отлично работает (я опустил обычный заголовок):

сервер. js

app.post('/upload', function(req, res, next){
    if (!req.files || Object.keys(req.files).length === 0) {
        return res.status(400).send('No file');
    }

    let sampleFile = req.files.archive;

    sampleFile.mv(`${pathtoupload}}/upload.js`, function(err) {
        if (err) return res.status(500).send(err);
        res.send('File uploaded!');
    })
})

index. html

<div class="card">
    <div class="card-body">
        <div class="row">
            <div class="col-12 col-sm-12">
                <form method="POST" encType="multipart/form-data">
                    <input type="file" name="archive" />
                    <button type="submit" class="btn btn-success btn-lg"><i class="material-icons">cloud_upload</i> Send</button>
                </form>  
            </div>
        </div>
    </div>
</div>

<script>
        $("form").submit(function(e){
            e.preventDefault()

            var formData = new FormData(this)

            $.ajax({
                url: '/upload',
                type: 'POST',
                data: formData,
                //dataType: 'application/octet-stream',
                cache: false,
                contentType: false,
                processData: false,
                xhr: function() {
                    var myXhr = $.ajaxSettings.xhr();
                    if (myXhr.upload) {
                        myXhr.upload.addEventListener('progress', function(a) {
                            console.log('P',a)
                        }, false);
                    }
                    return myXhr;
                },
                success: function(data) {
                    alert('ok',data)
                },
            });
        });
</script>

Вопрос: Как я могу получить куски JSON данных в express, проанализировать, а затем добавить в базу данных?

Возможно ли это, или я должен ждать завершения загрузки?

Я пытаюсь выполнить следующее безуспешно, нет отпечатков в консоли сервера, только «загрузка», но на клиенте я вижу в консоли загружаемые чанки

var JSONStream = require('JSONStream')
var es = require('event-stream')
var stream = require('stream');

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

    var readable = new stream.Readable({encoding: 'utf8'})

    req.on('data', function onRequestData(chunk){
        readable.push(chunk)
    })
    req.on('end', function(){
        res.send({})
    })

    var getStream = function () {
        parser = JSONStream.parse('*')
        return readable.pipe(parser)
    }

    getStream().pipe(es.mapSync(function(d){
        console.log(d)
        ///the pg insert part
    }))
})

1 Ответ

0 голосов
/ 22 февраля 2020

Я бы порекомендовал вам использовать pg-copy-streams для этого. Это позволяет вам передавать двоичные данные непосредственно в таблицу и из таблицы. Что именно то, что вам нужно. Вот пример, взятый со страницы NPM:

Передача из файла в таблицу

var fs = require('fs');
var {Pool} =

require('pg');
var copyFrom = require('pg-copy-streams').from;

var pool = new Pool();

pool.connect(function(err, client, done) {
  var stream = client.query(copyFrom('COPY my_table FROM STDIN'));
  var fileStream = fs.createReadStream('some_file.tsv')
  fileStream.on('error', done);
  stream.on('error', done);
  stream.on('end', done);
  fileStream.pipe(stream);
});
...