| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173 |
- <?php
- namespace App\Services;
- use Illuminate\Support\Facades\Http;
- use Illuminate\Support\Facades\Log;
- use Illuminate\Support\Facades\Storage;
- use Illuminate\Support\Str;
- class PdfStorageService
- {
- /**
- * 保存二进制 PDF,返回可访问 URL
- */
- public function put(string $path, string $binary): ?string
- {
- $driver = config('services.pdf_storage.driver', env('PDF_STORAGE_DRIVER', 'local'));
- return match ($driver) {
- 'upyun' => $this->putUpyun($path, $binary),
- 'chunsun' => $this->putChunsun($path, $binary),
- default => $this->putLocal($path, $binary),
- };
- }
- private function putLocal(string $path, string $binary): ?string
- {
- $disk = 'public';
- // 确保目录存在
- $dir = Str::beforeLast($path, '/');
- if ($dir && $dir !== $path) {
- Storage::disk($disk)->makeDirectory($dir);
- }
- $written = Storage::disk($disk)->put($path, $binary);
- if (!$written) {
- Log::error('PdfStorageService: 本地存储失败', ['path' => $path, 'disk' => $disk]);
- return null;
- }
- return url(Storage::url($path));
- }
- /**
- * 又拍云存储(REST API),需要以下 env:
- * PDF_STORAGE_DRIVER=upyun
- * UPYUN_BUCKET=xxx
- * UPYUN_OPERATOR=xxx
- * UPYUN_PASSWORD=xxx
- * UPYUN_DOMAIN=https://your.cdn.domain 或 https://v0.api.upyun.com
- */
- private function putUpyun(string $path, string $binary): ?string
- {
- $bucket = env('UPYUN_BUCKET');
- $operator = env('UPYUN_OPERATOR');
- $password = env('UPYUN_PASSWORD');
- $domain = rtrim(env('UPYUN_DOMAIN', 'https://v0.api.upyun.com'), '/');
- if (!$bucket || !$operator || !$password) {
- Log::error('PdfStorageService: 又拍云配置缺失', compact('bucket', 'operator'));
- return null;
- }
- $target = "{$domain}/{$bucket}/" . ltrim($path, '/');
- try {
- $response = Http::withHeaders([
- 'Content-Type' => 'application/pdf',
- 'Content-Length' => strlen($binary),
- ])
- ->withBasicAuth($operator, $password)
- ->timeout(30)
- ->withBody($binary, 'application/pdf')
- ->put($target);
- if (!$response->successful()) {
- Log::error('PdfStorageService: 又拍云上传失败', [
- 'status' => $response->status(),
- 'body' => $response->body(),
- 'target' => $target,
- ]);
- return null;
- }
- // 生成访问 URL,优先使用 CDN 域名
- $cdn = env('UPYUN_CDN_DOMAIN');
- if ($cdn) {
- return rtrim($cdn, '/') . '/' . ltrim($path, '/');
- }
- return $target;
- } catch (\Throwable $e) {
- Log::error('PdfStorageService: 又拍云异常', [
- 'error' => $e->getMessage(),
- 'target' => $target ?? null,
- ]);
- return null;
- }
- }
- /**
- * Chunsun云存储上传(POST multipart/form-data)
- * 环境变量:
- * PDF_STORAGE_DRIVER=chunsun
- * CHUNSUN_UPLOAD_URL=https://crmapi.dcjxb.yunzhixue.cn/file/upload
- */
- private function putChunsun(string $path, string $binary): ?string
- {
- $uploadUrl = env('CHUNSUN_UPLOAD_URL', 'https://crmapi.dcjxb.yunzhixue.cn/file/upload');
- try {
- // 获取扩展名并决定 MIME
- $extension = strtolower(pathinfo($path, PATHINFO_EXTENSION) ?: 'jpg');
- $mimeMap = [
- 'pdf' => 'application/pdf',
- 'md' => 'text/markdown',
- 'markdown' => 'text/markdown',
- 'txt' => 'text/plain',
- 'png' => 'image/png',
- 'jpg' => 'image/jpeg',
- 'jpeg' => 'image/jpeg',
- ];
- $mimeType = $mimeMap[$extension] ?? 'application/octet-stream';
- $baseName = basename($path);
- // 发送POST请求上传内容
- $response = Http::timeout(60)
- ->attach('file', $binary, $baseName, ['Content-Type' => $mimeType])
- ->post($uploadUrl);
- if (!$response->successful()) {
- Log::error('PdfStorageService: Chunsun上传失败', [
- 'status' => $response->status(),
- 'body' => $response->body(),
- 'url' => $uploadUrl,
- ]);
- return null;
- }
- $data = $response->json();
- // 检查响应格式
- if (!isset($data['code']) || $data['code'] !== 200) {
- Log::error('PdfStorageService: Chunsun上传失败,响应格式错误', [
- 'response' => $data,
- ]);
- return null;
- }
- // 检查返回数据
- if (!isset($data['data']['url'])) {
- Log::error('PdfStorageService: Chunsun上传失败,未返回URL', [
- 'response' => $data,
- ]);
- return null;
- }
- $uploadedUrl = $data['data']['url'];
- Log::info('PdfStorageService: Chunsun上传成功', [
- 'path' => $path,
- 'url' => $uploadedUrl,
- ]);
- return $uploadedUrl;
- } catch (\Throwable $e) {
- Log::error('PdfStorageService: Chunsun上传异常', [
- 'error' => $e->getMessage(),
- 'path' => $path,
- ]);
- return null;
- }
- }
- }
|