How to fetch the image files from a server and zip it in sailsjs

旧城冷巷雨未停 提交于 2019-12-10 22:38:44

问题


I want to zip all the images from s3 urls. I am doing it on server side on sailsjs framework.

I tried using axios to download the images and used 'zipdir'. The images are getting downloaded in temp folder. But its not getting zipped properly.

this.downloadFiles = function (req, res) {
    var resObj = {}
    async.waterfall([
        this.createFolder.bind(undefined, req),
        this.downloadFilesAxios.bind(undefined, req),
        this.zipTheFiles.bind(undefined, req)
    ], function final(err, result) {
        if (err) {
            console.log('SOME ERROR', err);
            resObj.statusCode = err.statusCode || 500;
        } else {
            resObj.statusCode = 200;
            resObj.result = result.questionList;
        }
        console.log('------', resObj.statusCode)
        resObj.messageKey = sails.config.statusCode[resObj.statusCode].key;
        resObj.message = sails.config.statusCode[resObj.statusCode].message;
        return res.send(resObj);
    });
};



}

this.downloadFilesAxios = function (req, obj, callback) {
    SurveyDocs.find({ surveyId: req.body.surveyId })
        .exec(function (err, docsDetails) {
            async.map(docsDetails, function (img, cb) {
                const url = img.docS3Url;

                let imageName = img.docFileName;
                const path = Path.resolve(__dirname, "temp", imageName);
                const writer = Fs.createWriteStream(path)

                Axios({
                    method: 'get',
                    url: url,
                    responseType: 'stream'
                })
                    .then(function (response) {
                        response.data.pipe(writer)
                    })
                writer.on('finish', (done) => {
                    console.log('success!!!');
                    cb(null, null)
                });
                writer.on('error', (err) => {
                    console.log('failed!!!');
                    cb(err, null)
                });

            }, (err, data) => {
                if (err) {
                    console.log('errrr', err);
                }
                callback(null, obj);
            });
        })
};

this.zipTheFiles = function (req, obj, callback) {
    var surveyId = req.body.surveyId;
    var tempDir = 'assets/zip/' + surveyId + '.zip'
    zipdir('temp', { saveTo: tempDir }, function (err, buffer) {
        callback(null, obj);
    });
    callback(null, obj);
}

Here I am getting a corrupt zip file. Please suggest the solution.


回答1:


I tried out your example there are a few things you need to consider in order to make it work.

const async = require('async');
const fs = require('fs');
const path = require('path');
const zipDir = require('zip-dir');
const axios = require('axios');
let writer;


async.waterfall([
  createFolder,
    downLoadFileAxios,
    zip

], function (err, result) {
  if (err) {
    console.log(err);
  } else {
    console.log('result :', result);
  }
});

let's assume this method creates the temp folder

function createFolder(callback) {
  setTimeout(function() {
    callback(null, 'temp');
  }, 1000);
}

Here the writeStream object and it's events should be put inside the then block. So that it writes the stream to the file correctly.

Another important thing here is you are not having a cath block attached the promise, so if any exception occurs it will be simply eaten up.

function downLoadFileAxios(dirPath, callback) {
  // Hard coded the images url for the sake of simplicity
  let files = [
    'https://free-images.com/lg/be5e/climbing_helmets_climbing_equipment.jpg',
    'https://free-images.com/lg/87ce/lilac_lilac_bush_lilac.jpg'
  ];

  async.mapSeries(files, function(img, cb) {
    let name = img.slice(img.lastIndexOf('/') + 1);
    let imagePath = path.resolve(__dirname, "newDir", name);
    writer = fs.createWriteStream(imagePath);
    axios({
      method: 'get',
      url: img,
      responseType: 'stream'
    }).
    then(function(response) {
      response.data.pipe(writer);
      writer.on('finish', (done) => {
        console.log('success!!!');
          cb(null, null)
      });
      writer.on('error', (err) => {
          console.log('failed!!!');
          cb(err, null)
      });
    })
    .catch((err) => {
      console.log(err);
    })
  }, function(err, result) {
    if (err) {
      console.log('errrr', err);
    }
    callback(null, 'done downloading');
  })

}


function zip (dirPath, callback) {
  let zipPath = path.resolve(__dirname, "assets", "file.zip");
  // console.log(`got directory path : ${dirPath}`);

  zipDir("newDir", {
    saveTo: zipPath
  }, function(err, buffer) {
      if(err) {
        callback(err, null);
      } else {
        callback(null, 'done');
      }
  });
}

This can be easily done using Async/Await like following.

const async = require('async');
const fs = require('fs');
const path = require('path');
const zipDir = require('zip-dir');
const axios = require('axios');
var writer;

// faking the directory creation part
async function createFolder(callback) {
 return new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(true);
  }, 2000);
 });
}

//Executes in the specified order.
(async () => {
  await createFolder();
  await downLoadFile();
  await zipTheFile();
})();

async function downLoadFile() {

  let files = [
    'https://free-images.com/lg/be5e/climbing_helmets_climbing_equipment.jpg',
    'https://free-images.com/lg/87ce/lilac_lilac_bush_lilac.jpg'
  ];

  for(let i= 0; i<files.length; i++) {
    await downLoadFileAxios(files[i]);
  }
}

async function downLoadFileAxios(url) {
  let name = url.slice(url.lastIndexOf('/') + 1);
  let imagePath = path.resolve(__dirname, "newDir", name);
  let writer = fs.createWriteStream(imagePath);

  const response = await axios({
    url,
    method: 'GET',
    responseType: 'stream'
  })

  response.data.pipe(writer)

  return new Promise((resolve, reject) => {
    writer.on('finish', resolve)
    writer.on('error', reject)
  })
}

function zipTheFile () {
  let zipPath = path.resolve(__dirname, "assets", "file.zip");
  return new Promise((resolve, reject) => {
    zipDir("newDir", {
      saveTo: zipPath
    }, function(err, buffer) {
        if(err) {
          return reject(err);
        }
        return resolve('done');
    });
  })
}

Hope this helps!.



来源:https://stackoverflow.com/questions/55841480/how-to-fetch-the-image-files-from-a-server-and-zip-it-in-sailsjs

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!