欢迎来到知了汇智!
联系电话:知了汇智-电话号码 028-62016472 / 13228113191

在express框架中调用系统命令生成/下载压缩文件-知了汇智

在express框架中调用系统命令生成/下载压缩文件

  目标

  使用nodejs的express框架完成一个rest接口,调用一个go语言编写的工具生成两个文件(为啥用go写这个工具,因为不会用js写),返回给前端一个压缩包,并对文件内容做一些业务处理。

在express框架中实现调用系统命令并生成、下载压缩文件

 

  调用

  使用child_process包,更多官方文档

const {spawn} = require('child_process');
 
const cmd = 'tools/finca';  
let args = ['-type=root'];
 
  let ls_root = spawn(cmd, args);
 
  ls_root.stdout.on('data', (data) => {
    logger.info(`stdout: ${data}`);
  });
 
  ls_root.stderr.on('data', (data) => {
    logger.error(`stderr: ${data}`);
  });
 
  ls_root.on('close', (code) => {
      logger.info(`finca tool process exited with code ${code}`);
  });

  压缩

  使用jszip包

const JSzip = require('jszip');
let zip = new JSzip();
zip.file(caRequest.commonName + "-cert.pem", CAResult.cert);
zip.file(caRequest.commonName + ".key", CAResult.privateKey);
let data = zip.generate({base64: false, compression: 'DEFLATE'});

  文件夹删除

  工具生成的文件和压缩文件均不保存,所有全部放在一个临时文件夹,结束后删除。

function deleteFolder(path) {
  let files = [];
  if (fs.existsSync(path)) {
    files = fs.readdirSync(path);
    files.forEach(function (file, index) {
      let curPath = path + "/" + file;
      if (fs.statSync(curPath).isDirectory()) { // recurse
        deleteFolder(curPath);
      } else { // delete file
        fs.unlinkSync(curPath);
      }
    });
    fs.rmdirSync(path);
  }
}

  实现rest接口

  这里最重要的是保证顺序执行

  util

  工具放在特定目录,一共生成了两个可执行文件,其中一个为.exe,方便在window环境下调试。调试时无需更改cmd,child_process调用时自动会根据操作系统调用.exe文件。

const {spawn} = require('child_process');
const fs = require("fs");
const Promise = require("bluebird");
const os = require('os');
const JSzip = require('jszip');
 
const certFileSuffix = "-cert.pem";
const priFileSuffix = "_sk";
const cmd = 'tools/finca';
let caUtil = {};
 
caUtil.createRootCA = function (caRequest, res) {
  let args = ['-type=root'];
  return createCA(caRequest, args, res);
};
 
caUtil.createClientCA = function 
(caRequest, res, rootCertBase64String, rootPrivateKeyBase64String, base64PublicKeyString) {
  let args = ['-type=client'];
  if (rootCertBase64String && rootPrivateKeyBase64String) {
    args.push('-rootCert=' + rootCertBase64String);
    args.push('-rootPri=' + rootPrivateKeyBase64String);
  } else {
    return Promise.reject('miss root CA')
  }
  return createCA(caRequest, args, res, base64PublicKeyString);
};
 
function createCA(caRequest, args, res, base64PublicKeyString) {
  let exitPubKey = false;
  let CAResult = {
    privateKey: '',
    cert: ''
  };
  let dir;
  if (base64PublicKeyString) {
    logger.info("public exit,do not create private key");
    exitPubKey = true;
    args.push('-clientPub=' + base64PublicKeyString)
  }
  if (caRequest.commonName) {
    args.push('-cn=' + caRequest.commonName);
    dir = os.tmpdir() + '/' + caRequest.commonName + '/';
    args.push('-dir=' + dir);
  } else {
    return Promise.reject("miss commonName")
  }
  if (caRequest.country) {
    args.push('-c=' + caRequest.country);
  }
  if (caRequest.effectiveDays) {
    args.push('-day=' + caRequest.effectiveDays);
  }
  if (caRequest.locality) {
    args.push('-l=' + caRequest.locality);
  }
  if (caRequest.organization) {
    args.push('-o=' + caRequest.organization);
  }
  if (caRequest.organizationalUnit) {
    args.push('-ou=' + caRequest.organizationalUnit);
  }
  if (caRequest.province) {
    args.push('-p=' + caRequest.province);
  }
  if (caRequest.role) {
    args.push('-role=' + caRequest.role);
  }
  logger.info("create CA args:", args);
  let ls_root = spawn(cmd, args);
 
  ls_root.stdout.on('data', (data) => {
    logger.info(`stdout: ${data}`);
  });
  ls_root.stderr.on('data', (data) => {
    logger.error(`stderr: ${data}`);
  });
  return new Promise(function (accept, reject) {
    ls_root.on('close', (code) => {
      logger.info(`finca tool process exited with code ${code}`);
      if (code === 0) {
        CAResult.cert = fs.readFileSync(dir + caRequest.commonName + certFileSuffix);
        if (!exitPubKey) {
          CAResult.privateKey = fs.readFileSync(dir + caRequest.commonName + priFileSuffix);
        }
        if (res) {
          logger.info(`do zip`);
          let zip = new JSzip();
          zip.file(caRequest.commonName + "-cert.pem", CAResult.cert);
          if (!exitPubKey) {
            zip.file(caRequest.commonName + ".key", CAResult.privateKey);
          }
          let data = zip.generate({base64: false, compression: 'DEFLATE'});
          res.set({
            'Content-Type': 'application/vnd.openxmlformats',
            "Content-Disposition": "attachment; filename=" + caRequest.commonName + ".zip"
          });
          res.end(data, 'binary');
        }
        logger.info(`ca tool work done, delete temp dir`);
        deleteFolder(dir);
        accept(CAResult);
      } else {
        reject("create CA error with code:", code)
      }
    })
  })
}
 
function deleteFolder(path) {
  let files = [];
  if (fs.existsSync(path)) {
    files = fs.readdirSync(path);
    files.forEach(function (file, index) {
      let curPath = path + "/" + file;
      if (fs.statSync(curPath).isDirectory()) { // recurse
        deleteFolder(curPath);
      } else { // delete file
        fs.unlinkSync(curPath);
      }
    });
    fs.rmdirSync(path);
  }
}
 
module.exports = caUtil;

  route

const express = require('express');
const router = express.Router();
const caUtil = require('../utils/caUtil');
 
router.post('/register', function (req, res, next) {
  let promise= caUtil.createRootCA(req.body,res);
  promise.then(CAResult=>{
    console.log("这里做一些业务相关操作",CAResult);
  })
});
 
module.exports = router;

  最后app.js添加引用

  mocha测试框架

const app = require("../app.js");
const supertest = require("supertest");
const should = require('should');
const request = supertest(app);
const caReq={
  commonName:"test.orgTest.cn",
  country:"CN",
  locality:"GuangDong",
  province:"ShenZhen",
  effectiveDays:365,
  organization:"xxxxx.orgTest.cn",
  organizationalUnit:"xxxxx",
  role:"admin"
};
 
describe('===组织管理测试===', function (done) {
  it("---组织注册成功---",function(done){
    request.post('/org/register')
      .send(caReq)
      .end(function (err, res) {
        console.log(res.body);
        done();
      });
  });
});

  这个测试看不出来下载效果,测试代码逻辑比较方便。可以启动项目用postman点击Send And Download试一下下载压缩文件即可。
 

       版权声明:本文来源于网络,由知了堂搜集整理,仅供大家学习前端时使用

132 2811 3191
预约免费试学
点击咨询
预约试学