2012-09-25 20 views
7

Soy bastante nuevo en node.js y estoy tratando de devolver un archivo zip que contiene los resultados de JSON. He estado tratando de averiguar cómo hacerlo, pero no he tenido los resultados esperados.JSON Zip Response en node.js

Estoy usando NodeJS, ExpressJS, LocomotiveJS, Mongoose y MongoDB.

Como estamos construyendo una aplicación orientada a dispositivos móviles, estoy intentando ahorrar tantos como ancho de banda como pueda.

La carga inicial diaria para la aplicación móvil podría ser un gran documento JSON, por lo que quiero comprimirlo antes de enviarlo al dispositivo. Si es posible, me gustaría hacer todo en la memoria para evitar la E/S del disco.

I trató con 3 bibliotecas hasta ahora:

  • adm-zip
  • nodo-zip
  • zipstream

El mejor resultado que he logrado está utilizando nodo-zip. Aquí está mi código:

return Queue.find({'owners': this.param('id')}).select('name extra_info cycle qtype purge purge_time tasks').exec(function (err, docs) { 
    if (!err) { 
     zip.file('queue.json', docs); 
     var data = zip.generate({base64:false,compression:'DEFLATE'}); 

     res.set('Content-Type', 'application/zip'); 
     return res.send(data); 
    } 
    else { 
     console.log(err); 
     return res.send(err); 
    } 
    }); 

El resultado es un archivo zip descargado, pero el contenido no se puede leer.

Estoy bastante seguro de que estoy mezclando cosas, pero hasta este punto no estoy seguro de cómo proceder.

¿Algún consejo?

Gracias de advace

Respuesta

17

Puede comprimir la producción en expreso 3 con esto:

app.configure(function(){ 
    //.... 
    app.use(express.compress()); 
}); 


app.get('/foo', function(req, res, next){ 
    res.send(json_data); 
}); 

Si el agente de usuario es compatible con gzip se gzip de forma automática.

+0

¡Gracias chovy, funcionó! – AkerbeltZ

+1

Yikes eso fue fácil. – prototype

+0

¿Dónde debo guardar middleware express.compress()? antes de las rutas y el contenido estático o después de ellos? – arunkjn

0

Creo que quieres decir cómo envío de contenido gzip con el nodo?

La versión de nodo 0.6 y superior tiene incorporado un módulo zlip, por lo que no es necesario solicitar módulos externos.

Puede enviar contenido de Gzip como este.

response.writeHead(200, { 'content-encoding': 'gzip' }); 
    json.pipe(zlib.createGzip()).pipe(response); 

Obviamente, necesitará primero tiempo cheque el cliente acepta la codificación gzip y también recordar gzip es una operación costosa por lo que debe almacenar en caché los resultados.

Aquí está llena ejemplo, tomando de la documentación

// server example 
// Running a gzip operation on every request is quite expensive. 
// It would be much more efficient to cache the compressed buffer. 
var zlib = require('zlib'); 
var http = require('http'); 
var fs = require('fs'); 
http.createServer(function(request, response) { 
    var raw = fs.createReadStream('index.html'); 
    var acceptEncoding = request.headers['accept-encoding']; 
    if (!acceptEncoding) { 
    acceptEncoding = ''; 
    } 

    // Note: this is not a conformant accept-encoding parser. 
    // See http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.3 
    if (acceptEncoding.match(/\bdeflate\b/)) { 
    response.writeHead(200, { 'content-encoding': 'deflate' }); 
    raw.pipe(zlib.createDeflate()).pipe(response); 
    } else if (acceptEncoding.match(/\bgzip\b/)) { 
    response.writeHead(200, { 'content-encoding': 'gzip' }); 
    raw.pipe(zlib.createGzip()).pipe(response); 
    } else { 
    response.writeHead(200, {}); 
    raw.pipe(response); 
    } 
}).listen(1337); 
+0

Hola Saeed, gracias por su respuesta. El problema es que la solución móvil que usamos (Titanium SDK) no admite archivos gzip. – AkerbeltZ

1

Para Express 4+, compress no viene incluido con Express y debe instalarse por separado.

$ npm install compression 

Luego de usar la biblioteca:

var compression = require('compression'); 
app.use(compression()); 

Hay un montón de opciones que puede ajustar, see here for the list.