Search code examples
node.jskoa

How to render response after stream finished pipe?


This is what I want, server is a file server, when client asks for certain file, it'll stream that file back. Instead of koi-static, I try to do this, but the dest.jpg only contains 'Not found'.

client code:

var Koa = require('koa');
var Router = require('koa-router');
const HttpStatus = require('http-status');
const fs = require('fs');
const koaBody = require('koa-body');
const request = require('request');

const tempSaveFile = fs.createWriteStream('dest.jpg');

const writeStream = request.post('http://localhost:3456/getfile/src.jpg').pipe(tempSaveFile);
writeStream.on('finish', () => {
    tempSaveFile.end();
    console.log('Upload successful! ');
});

server code:

var Koa = require('koa');
var Router = require('koa-router');
const HttpStatus = require('http-status');
const fs = require('fs');
const koaBody = require('koa-body');

var app = new Koa();
var router = new Router();
const serve = require('koa-static');

router
    .post([`/getfile/:fileName`],
        (ctx) => {
            const { params: { fileName } } = ctx;
            console.error(`------- server will return ${fileName} --------`);

            const readStream = fs.createReadStream(fileName).pipe(ctx.res);

            readStream.on('finish', () => {
                console.error('---- server finished stream ----');
                ctx.status = HttpStatus.OK;
            });
        })

app.use(router.routes());
app.use(router.allowedMethods());

app.listen(3456);

When I change the server to use koa-static, client can gets the file successfully, did diff, look the same.

I suspect server returns too fast before it finishes, but another post said this is the way to wait for pipe to finish. callback to handle completion of pipe Any suggestions ? thanks !


Solution

  • ok, I added async, working now

    const multiparty = require('multiparty');
    const multer = require('koa-multer');
    const request = require('request');
    
    var app = new Koa();
    var router = new Router();
    const serve = require('koa-static');
    
    const streamEnd = fd => new Promise((resolve, reject) => {
        fd.on('end', () => {console.error('-- 51 --'); resolve(51); });
        fd.on('finish', () => {console.error('-- 53 --'); resolve(53); });
        fd.on('error', reject);
    });
    
    router
        .get([`/getfile/:fileName`],
            async (ctx) => {
                const { params: { fileName } } = ctx;
                console.error(`------- server will return ${fileName} --------`);
    
                if (fs.existsSync(fileName)) {
                    const readStream = fs.createReadStream(fileName).pipe(ctx.res);
                    await streamEnd(readStream);
    
                    ctx.status = HttpStatus.OK;
                } else {
                    console.error(`File ${fileName} doesnot exist`);
                    ctx.status = HttpStatus.INTERNAL_SERVER_ERROR;
                }
            })
    
    app.use(serve('./customer'));
    app.use(router.routes());
    app.use(router.allowedMethods());
    
    app.listen(3456);