89 lines
2.7 KiB
PHP
89 lines
2.7 KiB
PHP
<?php
|
|
|
|
namespace App\Services\ESign;
|
|
|
|
use Illuminate\Http\UploadedFile;
|
|
use Illuminate\Support\Facades\Storage;
|
|
use Illuminate\Support\Str;
|
|
use RuntimeException;
|
|
|
|
class DocxToPdfConverter
|
|
{
|
|
/**
|
|
* Word 파일이면 PDF로 변환, PDF면 그대로 저장.
|
|
*
|
|
* @return array{path: string, name: string, hash: string, size: int}
|
|
*/
|
|
public function convertAndStore(UploadedFile $file, string $storagePath): array
|
|
{
|
|
if (! $this->isWordFile($file)) {
|
|
// PDF는 그대로 저장
|
|
$path = $file->store($storagePath, 'local');
|
|
|
|
return [
|
|
'path' => $path,
|
|
'name' => $file->getClientOriginalName(),
|
|
'hash' => hash_file('sha256', $file->getRealPath()),
|
|
'size' => $file->getSize(),
|
|
];
|
|
}
|
|
|
|
// Word → PDF 변환
|
|
$originalName = $file->getClientOriginalName();
|
|
$pdfName = preg_replace('/\.(docx?|DOCX?)$/', '.pdf', $originalName);
|
|
|
|
$tmpDir = sys_get_temp_dir().'/esign_convert_'.Str::random(16);
|
|
mkdir($tmpDir, 0755, true);
|
|
|
|
try {
|
|
$tmpWordPath = $tmpDir.'/'.'source.'.$file->getClientOriginalExtension();
|
|
copy($file->getRealPath(), $tmpWordPath);
|
|
|
|
$command = sprintf(
|
|
'HOME=%s libreoffice --headless --convert-to pdf --outdir %s %s 2>&1',
|
|
escapeshellarg($tmpDir),
|
|
escapeshellarg($tmpDir),
|
|
escapeshellarg($tmpWordPath)
|
|
);
|
|
|
|
exec($command, $output, $exitCode);
|
|
|
|
if ($exitCode !== 0) {
|
|
throw new RuntimeException(
|
|
'LibreOffice 변환 실패 (exit code: '.$exitCode.'): '.implode("\n", $output)
|
|
);
|
|
}
|
|
|
|
$tmpPdfPath = $tmpDir.'/source.pdf';
|
|
if (! file_exists($tmpPdfPath)) {
|
|
throw new RuntimeException('변환된 PDF 파일을 찾을 수 없습니다.');
|
|
}
|
|
|
|
$hash = hash_file('sha256', $tmpPdfPath);
|
|
$size = filesize($tmpPdfPath);
|
|
|
|
// 최종 저장 경로
|
|
$finalPath = $storagePath.'/'.Str::random(40).'.pdf';
|
|
Storage::disk('local')->put($finalPath, file_get_contents($tmpPdfPath));
|
|
|
|
return [
|
|
'path' => $finalPath,
|
|
'name' => $pdfName,
|
|
'hash' => $hash,
|
|
'size' => $size,
|
|
];
|
|
} finally {
|
|
// 임시 파일 정리
|
|
array_map('unlink', glob($tmpDir.'/*'));
|
|
@rmdir($tmpDir);
|
|
}
|
|
}
|
|
|
|
public function isWordFile(UploadedFile $file): bool
|
|
{
|
|
$ext = strtolower($file->getClientOriginalExtension());
|
|
|
|
return in_array($ext, ['doc', 'docx']);
|
|
}
|
|
}
|