UNPKG

@tasolutions/express-core

Version:
187 lines (159 loc) 7.26 kB
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}`); } }