1

I'm currently uploading files in skipper to skipper-s3, but I want to save multiple resized copies of the file. Is there a way to clone the file stream? I found this solution but can't find a way to spawn the file stream. Maybe there is a way that works. Anyways, here's the code of the upload:

  processUpload: function (req, res) {

    var type = req.param('type');
    if (type !== 'thumbnail' && type !== 'image' || typeof req.file('file')._files[0] == 'undefined') return res.badRequest();

    var dir = 'news/'+type+'/',
      filename = moment().unix() + '_' + req.file('file')._files[0].stream.filename,
      filetype = req.file('file')._files[0].stream.headers['content-type']
      filesize = req.file('file')._files[0].stream.byteCount;

    // Lowercase and convert spaces to hyphens
    filename = filename.toLowerCase()
             .replace(/ +/g,'-');

    if (filetype != 'image/jpeg' && filetype != 'image/png' && filetype != 'image/gif') return res.badRequest('File must be a JPG, GIF, or PNG');
    if (filesize > 2000000) return res.badRequest('File cannot exceed 2MB');

    var fs = require('fs')
      , gm = require('gm');

    var resizeStream = req.file('file')._files[0].stream;
    var bs = gm(resizeStream, 'img.jpg')
    .resize(100,100)
    .write('resize.jpg', function (err) { });


    req.file('file').upload({
      adapter: require('skipper-s3'),
      key: 'Axx',
      secret: 'xx',
      bucket: 'xx6',
      saveAs: dir+filename,
      headers: {
        'x-amz-acl': 'public-read'
      }
    }, function (err, filesUploaded) {
      if (err) return res.negotiate(err);

      return res.ok({
        trigger: 'article-'+type+'-uploaded',
        fileUploaded: filename,
        previewURL: 'https://s3.amazonaws.com/sdf/'+dir+filename,
      });
    });

  }

This doesn't work as once I resize and save the image, the .upload functionality has no stream to go off of. If you know of a good way to clone the stream or work around this problem, let me know. Thanks for checking out my question.

Community
  • 1
  • 1
Daniel Payne
  • 125
  • 8

1 Answers1

0

This is what I eventually got working, weird I know, but I used the skipper-s3 module for the first upload and aws-sdk for the subsequent ones, because they are promise dependent on the first one being done to copy. This seems like a less than ideal solution, but worked for me to stream one file to multiple buffered streams, resizing them through gm and uploading sizes to s3.

var fs = require('fs')
, gm = require('gm');

req.file('file').upload({
  adapter: require('skipper-s3'),
  key: 'Asdf234',
  secret: 'hehe',
  bucket: 'xd',
  function (file, cb) {
            if (allowedTypes.indexOf(file.headers['content-type']) === -1) return false;

            var extension = file.filename.split('.').pop();
            var clean = file.filename.toLowerCase()
                                .replace(/ +/g,'-');
            filename = moment().unix() + '_' + clean + '.' + extension;

            cb(null, dir+filename);
        },
  headers: {
    'x-amz-acl': 'public-read'
  }
}, function (err, filesUploaded) {
  if (err) return res.negotiate(err);


        var request = require('request');
        var AWS = require('aws-sdk');
        AWS.config.region = 'us-east-1';

        var s3obj = new AWS.S3({params: {Bucket: 'xd'}});

        gm(request(filesUploaded[0]['extra']['Location']),"/tmp/orig.jpg")
        .resize('750', '375')
        .stream(function (err, stdout, stderr) {

            var buf = new Buffer('');

            stdout.on('data',function(data) {
                buf = Buffer.concat([buf,data]);
            });

            stdout.on('end',function(data) {
                var params = {
                ACL: 'public-read',
                  Key: 'news/1/'+filename,
                  Body: buf};

                    s3obj.upload(params, function(err, data) {
                if (err) {
                  sails.log.debug("Error uploading data: ", err);
                } else {
                  sails.log.debug("Successfully uploaded data to myBucket/myKey");
                }
              });
            });
        });
Daniel Payne
  • 125
  • 8