123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674 |
- var request = require('request');
- var fs = require('fs');
- var ffmpeg = require('fluent-ffmpeg');
- var ljConst = require("../common/LjConst.js");
- var path = require('path');
- var logHelper = require("./LjLogHelper");
- var apiHelper = require("../helper/LjApiHelper");
- var httpHelper = require("../helper/LjHttpHelper");
- var os = require('os');
- /**
- * The helper of file
- */
- class LjFileHelper
- {
- /**
- * Download file
- * @param fileUrl the file url
- * @returns {boolean}
- */
- static downloadFile(fileUrl, opt)
- {
- if (fileUrl == null || fileUrl == "")
- {
- return "";
- }
- //获取文件属性对象
- var filePropObj = this.getFileProperty(fileUrl);
- if (filePropObj == null)
- {
- return false;
- }
- //视频处理
- if (filePropObj.fileType == ljConst.VIDEO_TYPE_M3U8)
- {
- //未加密视频本地存储路径
- var localFileDir = filePropObj.folderDir + filePropObj.fileName + ".mp4"
- //M3U8视频转换MP4
- ffmpeg(fileUrl).format(ljConst.VIDEO_TYPE_MP4)
- .on('start', function (err)
- {
- logHelper.info("【" + opt.lessonId + "】", "Starting down video:" + fileUrl);
- })
- .on('error', function (err)
- {
- logHelper.error("【" + opt.lessonId + "】", "Failed to down video[" + fileUrl + "]: " + err.message);
- })
- .on('end', function ()
- {
- //加密视频存储路径
- let localFileDirNew = filePropObj.folderDir + filePropObj.fileName + "_new" + ".mp4"
- logHelper.info("【" + opt.lessonId + "】", "Succeeded to down video:" + localFileDirNew);
- //加密存储
- LjFileHelper.writeEncryptedStream(localFileDir, localFileDirNew, function ()
- {
- LjFileHelper.updateDownloadResSize(opt);
- });
- if (fs.existsSync(localFileDir))
- {
- //删除文件(加密存储完成后删除未加密文件)
- fs.unlink(localFileDir, function (err)
- {
- if (err)
- {
- //删除失败
- logHelper.error("【" + opt.lessonId + "】", "Failed to delete video[" + err.message + "]:" + localFileDir);
- throw err;
- }
- else
- {
- logHelper.info("【" + opt.lessonId + "】", 'Succeeded to delete video:' + localFileDir)
- }
- });
- }
- })
- .save(localFileDir);
- }//有声读物处理
- else if (filePropObj.fileType == ljConst.VIDEO_TYPE_MP3)
- {
- //未加密有声读物本地存储地址
- var localFileDir = filePropObj.folderDir + filePropObj.fileName + "." + filePropObj.fileType;
- //读取有声读物
- request(fileUrl).pipe(fs.createWriteStream(localFileDir)).on('close', function ()
- {
- //加密有声读物存储地址
- var localFileDirNew = filePropObj.folderDir + filePropObj.fileName + "_new." + filePropObj.fileType;
- logHelper.info("【" + opt.lessonId + "】", "Succeeded to down audio:" + localFileDirNew);
- //加密有声读物
- LjFileHelper.writeEncryptedStream(localFileDir, localFileDirNew, function ()
- {
- /*//获取文件基本信息
- fs.stat(localFileDirNew, function (err, stats)
- {
- if (err == null)
- {
- //文件大小
- var fileSize = stats.size;
- LjFileHelper.updateDownloadResSize(opt);
- logHelper.info("Succeeded to encrypt audio:" + localFileDirNew + " with file size[" + fileSize + "]");
- }
- });*/
- LjFileHelper.updateDownloadResSize(opt);
- });
- if (fs.existsSync(localFileDir))
- {
- //删除文件(加密存储完成后删除未加密文件)
- fs.unlink(localFileDir, function (err)
- {
- if (err)
- {
- //删除失败
- logHelper.erro("【" + opt.lessonId + "】", "Failed to delete audio[" + err.message + "]:" + localFileDir);
- throw err;
- }
- else
- {
- logHelper.info("【" + opt.lessonId + "】", 'Succeeded to delete audio:' + localFileDir)
- }
- });
- }
- });
- }//图片处理
- else
- {
- //未加密图片本地存储地址
- var localFileDir = filePropObj.folderDir + filePropObj.fileName + "." + filePropObj.fileType;
- //读取图片
- request(fileUrl).pipe(fs.createWriteStream(localFileDir)).on('close', function ()
- {
- //加密图片存储地址
- var localFileDirNew = filePropObj.folderDir + filePropObj.fileName + "_new." + filePropObj.fileType;
- logHelper.info("【" + opt.lessonId + "】", "Succeeded to down image:" + localFileDirNew);
- //加密图片
- LjFileHelper.writeEncryptedStream(localFileDir, localFileDirNew, function ()
- {
- /* //获取文件基本信息
- fs.stat(localFileDirNew, function (err, stats)
- {
- if (err == null)
- {
- //文件大小
- var fileSize = stats.size;
- LjFileHelper.updateDownloadResSize(opt);
- logHelper.info("Succeeded to encrypt image:" + localFileDirNew + " with file size[" + fileSize + "]");
- }
- });*/
- LjFileHelper.updateDownloadResSize(opt);
- });
- if (fs.existsSync(localFileDir))
- {
- //删除文件(加密存储完成后删除未加密文件)
- fs.unlink(localFileDir, function (err)
- {
- if (err)
- {
- //删除失败
- logHelper.error("【" + opt.lessonId + "】", "Failed to delete image[" + err.message + "]:" + localFileDir);
- throw err;
- }
- else
- {
- logHelper.info("【" + opt.lessonId + "】", 'Succeeded to delete image:' + localFileDir)
- }
- });
- }
- });
- }
- }
- /**
- * Delete file
- * @param fileUrl the file url
- * @returns {boolean}
- */
- static delFile(fileUrl)
- {
- //获取文件属性对象
- var filePropObj = this.getFileProperty(fileUrl);
- if (filePropObj == null)
- {
- return false;
- }
- //视频处理
- if (filePropObj.fileType == ljConst.VIDEO_TYPE_M3U8)
- {
- //加密视频存储路径
- let localFileDirNew = filePropObj.folderDir + filePropObj.fileName + "_new" + ".mp4"
- if (fs.existsSync(localFileDirNew))
- {
- //删除加密文件
- fs.unlink(localFileDirNew, function (err)
- {
- if (err)
- {
- //删除失败
- logHelper.info("Failed to delete video[" + err.message + "]:" + localFileDir);
- throw err;
- }
- else
- {
- logHelper.info('Succeeded to delete video:' + localFileDir)
- }
- });
- }
- }//有声读物处理
- else if (filePropObj.fileType == ljConst.VIDEO_TYPE_MP3)
- {
- //未加密有声读物本地存储地址
- var localFileDir = filePropObj.folderDir + filePropObj.fileName + "." + filePropObj.fileType;
- //读取有声读物
- request(fileUrl).pipe(fs.createWriteStream(localFileDir)).on('close', function ()
- {
- //加密有声读物存储地址
- var localFileDirNew = filePropObj.folderDir + filePropObj.fileName + "_new." + filePropObj.fileType;
- if (fs.existsSync(localFileDirNew))
- {
- //删除文件(加密存储完成后删除未加密文件)
- fs.unlink(localFileDirNew, function (err)
- {
- if (err)
- {
- //删除失败
- logHelper.erro("【" + opt.lessonId + "】", "Failed to delete audio[" + err.message + "]:" + localFileDir);
- throw err;
- }
- else
- {
- logHelper.info("【" + opt.lessonId + "】", 'Succeeded to delete audio:' + localFileDir)
- }
- });
- }
- });
- }//图片处理
- else
- {
- //加密图片存储地址
- var localFileDirNew = filePropObj.folderDir + filePropObj.fileName + "_new." + filePropObj.fileType;
- if (fs.existsSync(localFileDirNew))
- {
- //删除加密文件
- fs.unlink(localFileDirNew, function (err)
- {
- if (err)
- {
- //删除失败
- logHelper.erro("Failed to delete image[" + err.message + "]:" + localFileDir);
- throw err;
- }
- else
- {
- logHelper.info('Succeeded to delete image:' + localFileDir)
- }
- });
- }
- }
- }
- /**
- * Gets file directory
- * @param fileName the file name
- * @returns {*|string} the file directory
- */
- static getFileDir(fileName)
- {
- var fileType = fileName.split(".")[1]
- var newFileDir = "";
- var platform = os.platform();
- if (platform == "win32")
- {
- if (fileType == "m3u8")
- {
- fileName = fileName.replace(".m3u8", "_new.mp4")
- newFileDir = ljConst.BASE_DIR + fileName.replace(/\*/g, '\\');
- }
- else
- {
- fileName = fileName.replace(".", "_new.")
- newFileDir = ljConst.BASE_DIR + fileName.replace(/\*/g, '\\');
- }
- }
- else if (platform == "darwin")
- {
- if (fileType == "m3u8")
- {
- fileName = fileName.replace(".m3u8", "_new.mp4")
- newFileDir = ljConst.BASE_DIR + fileName.replace(/\*/g, '/');
- }
- else
- {
- fileName = fileName.replace(".", "_new.")
- newFileDir = ljConst.BASE_DIR + fileName.replace(/\*/g, '/');
- }
- }
- return newFileDir;
- }
- /**
- * Makes directory
- * @param dirname the directory name
- * @returns {boolean} true or false
- */
- static mkdirsSync(dirname)
- {
- if (fs.existsSync(dirname))
- {
- return true;
- }
- else
- {
- if (this.mkdirsSync(path.dirname(dirname)))
- {
- fs.mkdirSync(dirname);
- return true;
- }
- }
- }
- /**
- * Gets the file property object
- * @param fileUrl the file URL
- * @returns {null}
- */
- static getFileProperty(fileUrl)
- {
- /*--文件夹目录-Begin--*/
- var folderDir = ljConst.BASE_DIR;
- var splitArr = fileUrl.split('/')
- var arrLen = splitArr.length;
- var platform = os.platform();
- if (platform == "win32")
- {
- for (var i = 3; i < arrLen - 1; i++)
- {
- folderDir += splitArr[i] + "\\";
- }
- }
- else if (platform == "darwin")
- {
- for (var i = 3; i < arrLen - 1; i++)
- {
- folderDir += splitArr[i] + "/";
- }
- }
- //创建文件夹目录
- this.mkdirsSync(folderDir);
- var filePropObj = {};
- filePropObj.folderDir = folderDir;
- //获取文件名称
- filePropObj.fileName = splitArr[arrLen - 1].split(".")[0];
- //获取文件类型
- filePropObj.fileType = splitArr[arrLen - 1].split(".")[1];
- /*--文件夹目录-Begin--*/
- return filePropObj;
- }
- /**
- * Gets the file property object
- * @param fileUrl the file URL
- * @returns {null}
- */
- static getFilePropertyNoMkdir(fileUrl)
- {
- if (fileUrl == null)
- {
- return;
- }
- /*--文件夹目录-Begin--*/
- var folderDir = ljConst.BASE_DIR;
- var splitArr = fileUrl.split('/')
- var arrLen = splitArr.length;
- var platform = os.platform();
- if (platform == "win32")
- {
- for (var i = 3; i < arrLen - 1; i++)
- {
- folderDir += splitArr[i] + "\\";
- }
- }
- else if (platform == "darwin")
- {
- for (var i = 3; i < arrLen - 1; i++)
- {
- folderDir += splitArr[i] + "/";
- }
- }
- var filePropObj = {};
- filePropObj.folderDir = folderDir;
- //获取文件名称
- filePropObj.fileName = splitArr[arrLen - 1].split(".")[0];
- //获取文件类型
- filePropObj.fileType = splitArr[arrLen - 1].split(".")[1];
- /*--文件夹目录-Begin--*/
- return filePropObj;
- }
- static Encrypted(c)
- {
- var b = '';
- for (var i = 0; i < c.length; i++)
- {
- var ch = c[i];
- if (ch == '0')
- {
- ch = 'f';
- }
- else if (ch == 'f')
- {
- ch = '0';
- }
- b = b + ch;
- //console.log(ch);
- }
- return b;
- }
- static Decrypted(c)
- {
- var b = '';
- for (var i = 0; i < c.length; i++)
- {
- var ch = c[i];
- if (ch == 'f')
- {
- ch = '0';
- }
- else if (ch == '0')
- {
- ch = 'f';
- }
- b = b + ch;
- //console.log(ch);
- }
- return b;
- }
- /**
- * Writes encrypted content, which is read from given source file, into given dest file
- * @param fSrc the source file
- * @param fDest the dest file
- */
- static writeEncryptedStream(fSrc, fDest, callback)
- {
- var rs = fs.createReadStream(fSrc);
- var ws = fs.createWriteStream(fDest);
- rs.on('data', function (chunk)
- {
- let b = new Buffer(chunk, 'hex');
- //console.log(b);
- let c = b.toString('hex');
- c = LjFileHelper.encryptedContent(c);
- let d = Buffer.from(c, 'hex');
- ws.write(d);
- });
- rs.on('end', function ()
- {
- ws.end();
- logHelper.info('Succeeded in writing into encrypted stream[' + fDest + '].');
- callback();
- });
- rs.on('error', function (err)
- {
- logHelper.error(err.stack);
- });
- }
- /**
- * Encrypts the content
- * @param c the content to be encrypted
- * @return the encrypted content
- */
- static encryptedContent(c)
- {
- var b = '';
- for (var i = 0; i < c.length; i++)
- {
- var ch = c[i];
- if (ch == '0')
- {
- ch = 'f';
- }
- else if (ch == 'f')
- {
- ch = '0';
- }
- else if (ch == '1')
- {
- ch = 'e';
- }
- else if (ch == 'e')
- {
- ch = '1';
- }
- else if (ch == '2')
- {
- ch = 'd';
- }
- else if (ch == 'd')
- {
- ch = '2';
- }
- else if (ch == '3')
- {
- ch = 'c';
- }
- else if (ch == 'c')
- {
- ch = '3';
- }
- b = b + ch;
- //console.log(ch);
- }
- return b;
- }
- /**
- * Decrypts the encrypted content
- * @param c the encrypted content
- * @return the decrypted content
- */
- static decryptedContent(c)
- {
- var b = '';
- for (var i = 0; i < c.length; i++)
- {
- var ch = c[i];
- if (ch == 'f')
- {
- ch = '0';
- }
- else if (ch == '0')
- {
- ch = 'f';
- }
- else if (ch == 'e')
- {
- ch = '1';
- }
- else if (ch == '1')
- {
- ch = 'e';
- }
- else if (ch == 'd')
- {
- ch = '2';
- }
- else if (ch == '2')
- {
- ch = 'd';
- }
- else if (ch == 'c')
- {
- ch = '3';
- }
- else if (ch == '3')
- {
- ch = 'c';
- }
- b = b + ch;
- //console.log(ch);
- }
- return b;
- }
- /**
- * Reads decrypted content, which is read from given encrypted file, into HTTP response stream
- * @param res the HTTP response stream
- * @param fDest the encrypted file
- */
- static readDecryptedStream(res, fDest, contentType)
- {
- res.writeHead(200, {'Content-Type': contentType});
- var rs = fs.createReadStream(fDest);
- rs.on('data', function (chunk)
- {
- let b = new Buffer(chunk, 'hex');
- let c = b.toString('hex');
- c = LjFileHelper.decryptedContent(c);
- let d = Buffer.from(c, 'hex');
- res.write(d);
- });
- rs.on('end', function ()
- {
- res.end();
- logHelper.log('Succeeded in reading from decrypted stream[' + fDest + '].');
- });
- rs.on('error', function (err)
- {
- logHelper.log(err.stack);
- });
- }
- static updateDownloadResSize(opt)
- {
- //return false;
- opt.url = apiHelper.getApiForUpdateResSize(opt.lessonId);
- opt.method = "PUT";
- opt.path = "/callback/download/update/resource/size";
- httpHelper.request(opt, function (error, res, body)
- {
- var retObj = JSON.parse(body);
- if (retObj.code == 200)
- {
- logHelper.info("Succeed to call api[" + opt.path + "]");
- return true;
- }
- else
- {
- logHelper.error("Failed to call api[" + opt.path + "],caused by error[" + retObj.message + "]");
- return false;
- }
- });
- }
- /**
- * Is video
- * @param dir the directory
- * @returns {boolean}
- */
- isVideo(dir)
- {
- if (dir == "")
- {
- return false;
- }
- var fileType = dir.split(".")[1];
- if ("m3u8" == fileType)
- {
- return true;
- }
- return false;
- }
- }
- module.exports = LjFileHelper;
|