Piping a file straight to the client using Node.js and Amazon S3












1















So I want to pipe a file straight to the client; how I am currently doing it is create a file to disk, then sending that file straight to the client.



router.get("/download/:name", async (req, res) => {

const s3 = new aws.S3();
const dir = "uploads/" + req.params.name + ".apkg"
let file = fs.createWriteStream(dir);

await s3.getObject({
Bucket: <bucket-name>,
Key: req.params.name + ".apkg"
}).createReadStream().pipe(file);

await res.download(dir);
});


I just looked up that res.download() only serves locally. Is there a way you can do it directly from AWS S3 to Client download? i.e. pipe files straight to user. Thanks in advance










share|improve this question



























    1















    So I want to pipe a file straight to the client; how I am currently doing it is create a file to disk, then sending that file straight to the client.



    router.get("/download/:name", async (req, res) => {

    const s3 = new aws.S3();
    const dir = "uploads/" + req.params.name + ".apkg"
    let file = fs.createWriteStream(dir);

    await s3.getObject({
    Bucket: <bucket-name>,
    Key: req.params.name + ".apkg"
    }).createReadStream().pipe(file);

    await res.download(dir);
    });


    I just looked up that res.download() only serves locally. Is there a way you can do it directly from AWS S3 to Client download? i.e. pipe files straight to user. Thanks in advance










    share|improve this question

























      1












      1








      1


      1






      So I want to pipe a file straight to the client; how I am currently doing it is create a file to disk, then sending that file straight to the client.



      router.get("/download/:name", async (req, res) => {

      const s3 = new aws.S3();
      const dir = "uploads/" + req.params.name + ".apkg"
      let file = fs.createWriteStream(dir);

      await s3.getObject({
      Bucket: <bucket-name>,
      Key: req.params.name + ".apkg"
      }).createReadStream().pipe(file);

      await res.download(dir);
      });


      I just looked up that res.download() only serves locally. Is there a way you can do it directly from AWS S3 to Client download? i.e. pipe files straight to user. Thanks in advance










      share|improve this question














      So I want to pipe a file straight to the client; how I am currently doing it is create a file to disk, then sending that file straight to the client.



      router.get("/download/:name", async (req, res) => {

      const s3 = new aws.S3();
      const dir = "uploads/" + req.params.name + ".apkg"
      let file = fs.createWriteStream(dir);

      await s3.getObject({
      Bucket: <bucket-name>,
      Key: req.params.name + ".apkg"
      }).createReadStream().pipe(file);

      await res.download(dir);
      });


      I just looked up that res.download() only serves locally. Is there a way you can do it directly from AWS S3 to Client download? i.e. pipe files straight to user. Thanks in advance







      node.js express download aws-sdk-js aws-sdk-nodejs






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 24 '18 at 0:14









      perjermerperjermer

      62




      62
























          2 Answers
          2






          active

          oldest

          votes


















          1














          As described in this SO thread:

          You can simply pipe the read stream into the response instead of the piping it to the file, just make sure to supply the correct Content-Type and to set it as an attachment, so the browser will know how to handle the response properly.



          res.attachment(req.params.name);
          await s3.getObject({
          Bucket: <bucket-name>,
          Key: req.params.name + ".apkg"
          }).createReadStream().pipe(res);


          On more pattern for this is to create a signed url directly to the S3 object and then let the client download straight from S3, instead of streaming it from your node webserver. This will reduce the workload from your web server.



          You will need to use the getSignedUrl method from the AWS S3 SDK for JS.

          Then, Once you have the URL, just return it to your client to download the file by themselves.



          You should take into account that once you give the client a signed URL that has download permissions for, say, 5 minutes, they will only be able to download that file during those next 5 minutes. And you should also take into account that they will be able to pass that URL to anyone else for download during those 5 minutes, so it is dependant on how secure you need this to be.






          share|improve this answer































            0














            S3 can be used to content so I would do the following.




            1. Add CORS headers on your node response. This will enable browser to download from another origin i.e. S3.

            2. Enable S3 web server on your bucket.

            3. Script to download redirect from S3 - this you could achieve in JS.


            Use signed URL as suggested in the other post if you need to protect S3 content.






            share|improve this answer























              Your Answer






              StackExchange.ifUsing("editor", function () {
              StackExchange.using("externalEditor", function () {
              StackExchange.using("snippets", function () {
              StackExchange.snippets.init();
              });
              });
              }, "code-snippets");

              StackExchange.ready(function() {
              var channelOptions = {
              tags: "".split(" "),
              id: "1"
              };
              initTagRenderer("".split(" "), "".split(" "), channelOptions);

              StackExchange.using("externalEditor", function() {
              // Have to fire editor after snippets, if snippets enabled
              if (StackExchange.settings.snippets.snippetsEnabled) {
              StackExchange.using("snippets", function() {
              createEditor();
              });
              }
              else {
              createEditor();
              }
              });

              function createEditor() {
              StackExchange.prepareEditor({
              heartbeatType: 'answer',
              autoActivateHeartbeat: false,
              convertImagesToLinks: true,
              noModals: true,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: 10,
              bindNavPrevention: true,
              postfix: "",
              imageUploader: {
              brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
              contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
              allowUrls: true
              },
              onDemand: true,
              discardSelector: ".discard-answer"
              ,immediatelyShowMarkdownHelp:true
              });


              }
              });














              draft saved

              draft discarded


















              StackExchange.ready(
              function () {
              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53454122%2fpiping-a-file-straight-to-the-client-using-node-js-and-amazon-s3%23new-answer', 'question_page');
              }
              );

              Post as a guest















              Required, but never shown

























              2 Answers
              2






              active

              oldest

              votes








              2 Answers
              2






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes









              1














              As described in this SO thread:

              You can simply pipe the read stream into the response instead of the piping it to the file, just make sure to supply the correct Content-Type and to set it as an attachment, so the browser will know how to handle the response properly.



              res.attachment(req.params.name);
              await s3.getObject({
              Bucket: <bucket-name>,
              Key: req.params.name + ".apkg"
              }).createReadStream().pipe(res);


              On more pattern for this is to create a signed url directly to the S3 object and then let the client download straight from S3, instead of streaming it from your node webserver. This will reduce the workload from your web server.



              You will need to use the getSignedUrl method from the AWS S3 SDK for JS.

              Then, Once you have the URL, just return it to your client to download the file by themselves.



              You should take into account that once you give the client a signed URL that has download permissions for, say, 5 minutes, they will only be able to download that file during those next 5 minutes. And you should also take into account that they will be able to pass that URL to anyone else for download during those 5 minutes, so it is dependant on how secure you need this to be.






              share|improve this answer




























                1














                As described in this SO thread:

                You can simply pipe the read stream into the response instead of the piping it to the file, just make sure to supply the correct Content-Type and to set it as an attachment, so the browser will know how to handle the response properly.



                res.attachment(req.params.name);
                await s3.getObject({
                Bucket: <bucket-name>,
                Key: req.params.name + ".apkg"
                }).createReadStream().pipe(res);


                On more pattern for this is to create a signed url directly to the S3 object and then let the client download straight from S3, instead of streaming it from your node webserver. This will reduce the workload from your web server.



                You will need to use the getSignedUrl method from the AWS S3 SDK for JS.

                Then, Once you have the URL, just return it to your client to download the file by themselves.



                You should take into account that once you give the client a signed URL that has download permissions for, say, 5 minutes, they will only be able to download that file during those next 5 minutes. And you should also take into account that they will be able to pass that URL to anyone else for download during those 5 minutes, so it is dependant on how secure you need this to be.






                share|improve this answer


























                  1












                  1








                  1







                  As described in this SO thread:

                  You can simply pipe the read stream into the response instead of the piping it to the file, just make sure to supply the correct Content-Type and to set it as an attachment, so the browser will know how to handle the response properly.



                  res.attachment(req.params.name);
                  await s3.getObject({
                  Bucket: <bucket-name>,
                  Key: req.params.name + ".apkg"
                  }).createReadStream().pipe(res);


                  On more pattern for this is to create a signed url directly to the S3 object and then let the client download straight from S3, instead of streaming it from your node webserver. This will reduce the workload from your web server.



                  You will need to use the getSignedUrl method from the AWS S3 SDK for JS.

                  Then, Once you have the URL, just return it to your client to download the file by themselves.



                  You should take into account that once you give the client a signed URL that has download permissions for, say, 5 minutes, they will only be able to download that file during those next 5 minutes. And you should also take into account that they will be able to pass that URL to anyone else for download during those 5 minutes, so it is dependant on how secure you need this to be.






                  share|improve this answer













                  As described in this SO thread:

                  You can simply pipe the read stream into the response instead of the piping it to the file, just make sure to supply the correct Content-Type and to set it as an attachment, so the browser will know how to handle the response properly.



                  res.attachment(req.params.name);
                  await s3.getObject({
                  Bucket: <bucket-name>,
                  Key: req.params.name + ".apkg"
                  }).createReadStream().pipe(res);


                  On more pattern for this is to create a signed url directly to the S3 object and then let the client download straight from S3, instead of streaming it from your node webserver. This will reduce the workload from your web server.



                  You will need to use the getSignedUrl method from the AWS S3 SDK for JS.

                  Then, Once you have the URL, just return it to your client to download the file by themselves.



                  You should take into account that once you give the client a signed URL that has download permissions for, say, 5 minutes, they will only be able to download that file during those next 5 minutes. And you should also take into account that they will be able to pass that URL to anyone else for download during those 5 minutes, so it is dependant on how secure you need this to be.







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Dec 16 '18 at 10:55









                  Chaos MonkeyChaos Monkey

                  452212




                  452212

























                      0














                      S3 can be used to content so I would do the following.




                      1. Add CORS headers on your node response. This will enable browser to download from another origin i.e. S3.

                      2. Enable S3 web server on your bucket.

                      3. Script to download redirect from S3 - this you could achieve in JS.


                      Use signed URL as suggested in the other post if you need to protect S3 content.






                      share|improve this answer




























                        0














                        S3 can be used to content so I would do the following.




                        1. Add CORS headers on your node response. This will enable browser to download from another origin i.e. S3.

                        2. Enable S3 web server on your bucket.

                        3. Script to download redirect from S3 - this you could achieve in JS.


                        Use signed URL as suggested in the other post if you need to protect S3 content.






                        share|improve this answer


























                          0












                          0








                          0







                          S3 can be used to content so I would do the following.




                          1. Add CORS headers on your node response. This will enable browser to download from another origin i.e. S3.

                          2. Enable S3 web server on your bucket.

                          3. Script to download redirect from S3 - this you could achieve in JS.


                          Use signed URL as suggested in the other post if you need to protect S3 content.






                          share|improve this answer













                          S3 can be used to content so I would do the following.




                          1. Add CORS headers on your node response. This will enable browser to download from another origin i.e. S3.

                          2. Enable S3 web server on your bucket.

                          3. Script to download redirect from S3 - this you could achieve in JS.


                          Use signed URL as suggested in the other post if you need to protect S3 content.







                          share|improve this answer












                          share|improve this answer



                          share|improve this answer










                          answered Dec 16 '18 at 13:49









                          Sid MalaniSid Malani

                          1,79711011




                          1,79711011






























                              draft saved

                              draft discarded




















































                              Thanks for contributing an answer to Stack Overflow!


                              • Please be sure to answer the question. Provide details and share your research!

                              But avoid



                              • Asking for help, clarification, or responding to other answers.

                              • Making statements based on opinion; back them up with references or personal experience.


                              To learn more, see our tips on writing great answers.




                              draft saved


                              draft discarded














                              StackExchange.ready(
                              function () {
                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53454122%2fpiping-a-file-straight-to-the-client-using-node-js-and-amazon-s3%23new-answer', 'question_page');
                              }
                              );

                              Post as a guest















                              Required, but never shown





















































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown

































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown







                              Popular posts from this blog

                              404 Error Contact Form 7 ajax form submitting

                              How to know if a Active Directory user can login interactively

                              TypeError: fit_transform() missing 1 required positional argument: 'X'