1

my node.js app connects through var socket = net.createConnection(port, ip); to download a file from another server. As soon as connection is made the server sends the file as data.

I catch it then by doing

socket.on('data', function(data) {

}).on('connect', function() {

}).on('end', function() {
console.log('DONE');
});

My initial goal is, to download the file using the method above and at the same time give the bytes to the client's browser as a downloadable file. For example: user clicks a button on the site which triggers the server-side download function and the user gets the file-save prompt. Node.JS then downloads the file from the remote server and at the same time gives each new byte to the user at the browser client. Is this possible? I imagine it would need to send headers of octet-stream to trigger file transfer between browser Node.JS. But how?

Update

Now I tried the code below with the help of the answer below:

app.get('/download', function (req, res) {

res.setHeader('Content-disposition', 'attachment; filename=' + "afile.txt");
res.setHeader('Content-Length', "12468")

var socket = net.createConnection(1024, "localhost");
console.log('Socket created.');
socket.on('data', function(data) {

    socket.pipe(res)

}).on('connect', function() {
// // Manually write an HTTP request.
// socket.write("GET / HTTP/1.0\r\n\r\n");
}).on('end', function() {
    console.log('DONE');
    socket.end();
});

 });

The data is being sent to the user's browser as a download, but the end result is a broken file. I checked the contents within and it seeems that something along the process causes the file to corrupt. I think now I have to write byte per byte? rather than doing socket.pipe?

robertklep
  • 198,204
  • 35
  • 394
  • 381
Zakukashi
  • 566
  • 1
  • 13
  • 29
  • 1
    You can't do that, but you can receive the whole file in memory using sockets and then make the user download the file using a data URI. Like so: http://stackoverflow.com/questions/3665115/create-a-file-in-memory-for-user-to-download-not-through-server. Streaming the file directly for the user to download however isn't possible using websockets. – Kerstomaat Jan 07 '14 at 01:28
  • File download is only avaialable over http. That interface is not there for websocket as sending file over it is yet to be standardised. See another similar question http://stackoverflow.com/questions/9871357/receive-file-via-websocket-and-initiate-download-dialog. – user568109 Jan 07 '14 at 06:19
  • You are mixing on('data') and pipe. Your first chunk of data is lost when you attach `.pipe` – Andrey Sidorov Jan 07 '14 at 13:20

3 Answers3

2

You need to set content-disposition header in your http response:

  response.writeHead(200, {
    'Content-Disposition': 'attachment; filename=genome.jpeg; modification-date="Wed, 12 Feb 1997 16:29:51 -0500"'
  });
  yourDataStream.pipe(response);

see RFC2183

Andrey Sidorov
  • 24,905
  • 4
  • 62
  • 75
2

It looks like you may want this:

app.get('/download', function (req, res) {
  res.attachment('afile.txt');
  require('http').get('http://localhost:1234/', function(response) {
    response.pipe(res);
  }).on('error', function(err) {
    res.send(500, err.message);
  });
});
robertklep
  • 198,204
  • 35
  • 394
  • 381
0

I found the solution! by doing res.write(d) i was able to direct the bytes from the other connection to the user browser download.

app.get('/download', function (req, res) {

res.setHeader('Content-disposition', 'attachment; filename=' + "afile.jpg");
res.setHeader('Content-Length', "383790");
res.setHeader('Content-Type','image/jpeg');

var socket = net.createConnection(1024, "localhost");
console.log('Socket created.');
//socket.setEncoding("utf8");
socket.on('data', function(d) {
    console.log(d);
    res.write(d);
}).on('connect', function() {
// // Manually write an HTTP request.
// socket.write("GET / HTTP/1.0\r\n\r\n");
}).on('end', function() {
    console.log('DONE');
    socket.end();
});


});
Ajay
  • 4,773
  • 3
  • 23
  • 36
Zakukashi
  • 566
  • 1
  • 13
  • 29