@tasolutions/express-core
Version:
All libs for express
187 lines (159 loc) • 7.26 kB
JavaScript
const axios = require('axios');
const { PDFDocument } = require('pdf-lib');
const Response = require('../../../../utils/response');
const { httpStatus } = require('../../../../utils/httpStatus');
const { DocumentMedia } = require('../models');
const { upload } = require('../../../../utils/s3Upload');
const { awsInfo } = require('../../../../config');
const { sendMessage } = require('../../../../clients/discord');
/**
* Export nhiều file PDF từ DocumentMedia và kết hợp thành một file duy nhất
* @param {Object} req - Request object
* @param {Object} res - Response object
* @param {Object} Collection - Collection model
* @param {Object} configs - Config options
*/
exports.exportMedias = async (req, res, Collection, configs) => {
try {
// Xác định nếu request là GET hoặc POST và lấy tham số tương ứng
const isGetRequest = req.method === 'GET';
// Lấy các tham số từ request (từ query nếu là GET, từ body nếu là POST)
let filters = {};
let mediaIds = [];
let exportName = `combined-export-${Date.now()}`;
if (isGetRequest) {
// Xử lý tham số từ query string
const { document_template_id, file_type, collection_name, ref_id, name, ...otherParams } = req.query;
if (name) exportName = name;
// Xây dựng filters từ query params
if (document_template_id) filters.document_template_id = document_template_id;
if (file_type) filters.file_type = file_type;
if (collection_name) filters.collection_name = collection_name;
if (ref_id) filters.ref_id = ref_id;
// Thêm các tham số khác vào filters nếu có
Object.keys(otherParams).forEach(key => {
filters[key] = otherParams[key];
});
} else {
// Xử lý tham số từ request body (POST)
filters = req.body.filters || {};
mediaIds = req.body.mediaIds || [];
if (req.body.name) exportName = req.body.name;
}
// Kiểm tra xem có cung cấp filters hoặc mediaIds không
if (Object.keys(filters).length === 0 && (!mediaIds || mediaIds.length === 0)) {
return Response.error(
res,
'Vui lòng cung cấp filters hoặc danh sách mediaIds',
httpStatus.BAD_REQUEST
);
}
// Xây dựng query để tìm các DocumentMedia
let query = {};
// Nếu có mediaIds, sử dụng chúng
if (mediaIds && mediaIds.length > 0) {
query._id = { $in: mediaIds };
}
// Nếu không, sử dụng filters
else if (Object.keys(filters).length > 0) {
query = { ...filters };
}
// Đảm bảo chỉ lấy các file PDF nếu không có filter file_type
if (!query.file_type) {
query.file_type = 'PDF';
}
console.log('[INFO] Query for documents:', query);
// Tìm các DocumentMedia theo query
const mediaFiles = await DocumentMedia.find(query).lean();
if (!mediaFiles || mediaFiles.length === 0) {
return Response.error(
res,
'Không tìm thấy tài liệu nào phù hợp với điều kiện',
httpStatus.NOT_FOUND
);
}
console.log(`[INFO] Tìm thấy ${mediaFiles.length} tài liệu để export`);
sendMessage(`[INFO][DOCUMENT][exportMedias] Tìm thấy ${mediaFiles.length} tài liệu để export`);
// Kết hợp các file PDF thành một file duy nhất
const combinedPdfUrl = await combineMediaFiles(mediaFiles, exportName);
return Response.success(
res,
{
url: combinedPdfUrl,
count: mediaFiles.length,
name: exportName
},
'Export tài liệu thành công'
);
} catch (error) {
console.error('Export media error:', error);
sendMessage(`[ERROR][DOCUMENT][exportMedias] ${error.message || 'Lỗi khi export tài liệu'}`);
return Response.error(
res,
error.message || 'Lỗi khi export tài liệu',
httpStatus.INTERNAL_SERVER_ERROR
);
}
};
/**
* Hàm xử lý kết hợp các file PDF
* @param {Array} mediaFiles - Danh sách các file media
* @param {String} exportName - Tên file export
* @returns {String} - URL của file PDF đã được kết hợp
*/
async function combineMediaFiles(mediaFiles, exportName) {
try {
// Tạo một tài liệu PDF mới
const mergedPdf = await PDFDocument.create();
// Lặp qua từng file media để tải và kết hợp
for (const media of mediaFiles) {
try {
// Tải nội dung file PDF từ URL
const pdfBytes = await downloadPdf(media.file_url);
// Đọc tài liệu PDF từ buffer
const pdfDoc = await PDFDocument.load(pdfBytes);
// Sao chép tất cả các trang từ tài liệu nguồn vào tài liệu đích
const copiedPages = await mergedPdf.copyPages(pdfDoc, pdfDoc.getPageIndices());
// Thêm các trang đã sao chép vào tài liệu đích
copiedPages.forEach((page) => {
mergedPdf.addPage(page);
});
console.log(`[INFO] Đã thêm tài liệu: ${media.name || media._id}`);
} catch (error) {
console.error(`[ERROR] Không thể thêm tài liệu ${media._id}: ${error.message}`);
// Tiếp tục với file tiếp theo nếu có lỗi với file hiện tại
continue;
}
}
// Lưu tài liệu PDF đã kết hợp thành buffer
const mergedPdfBytes = await mergedPdf.save();
// Upload file PDF đã kết hợp lên S3
const fileName = `${exportName}.pdf`;
const uploadResult = await upload({
Bucket: awsInfo.s3Info.bucket,
Key: `documents/exports/${fileName}`,
Body: Buffer.from(mergedPdfBytes),
ContentType: 'application/pdf',
});
console.log(`[SUCCESS] Đã tạo và upload file PDF kết hợp: ${fileName}`);
// Trả về URL của file đã upload
return uploadResult.Location;
} catch (error) {
console.error(`[ERROR] Lỗi khi kết hợp các file PDF: ${error.message}`);
throw new Error(`Lỗi khi kết hợp các file PDF: ${error.message}`);
}
}
/**
* Tải file PDF từ URL
* @param {String} url - URL của file PDF
* @returns {Buffer} - Buffer chứa nội dung file PDF
*/
async function downloadPdf(url) {
try {
const response = await axios.get(url, { responseType: 'arraybuffer' });
return Buffer.from(response.data);
} catch (error) {
console.error(`[ERROR] Không thể tải file từ URL ${url}: ${error.message}`);
throw new Error(`Không thể tải file từ URL: ${error.message}`);
}
}