| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179 |
- <?php
- namespace App\Services\Storage;
- use Illuminate\Support\Facades\Http;
- use Illuminate\Support\Facades\Log;
- use Illuminate\Support\Facades\Storage;
- class ChunsunUploader
- {
- /**
- * 从 URL 上传图片到春笋云
- */
- public function uploadFromUrl(string $url): string
- {
- try {
- // 1. 下载图片
- $response = Http::timeout(30)->get($url);
- if (!$response->successful()) {
- throw new \Exception("Failed to download image from URL: {$url}");
- }
- $imageContent = $response->body();
- $mimeType = $response->header('Content-Type', 'image/jpeg');
- // 2. 创建临时文件
- $extension = $this->getExtensionFromMimeType($mimeType);
- $tempFileName = 'temp_' . uniqid() . '.' . $extension;
- $tempPath = sys_get_temp_dir() . '/' . $tempFileName;
- file_put_contents($tempPath, $imageContent);
- // 3. 上传到春笋云
- $uploadedUrl = $this->uploadToChunsun($tempPath, $tempFileName);
- // 4. 清理临时文件
- @unlink($tempPath);
- return $uploadedUrl;
- } catch (\Exception $e) {
- Log::error('Chunsun upload failed', [
- 'url' => $url,
- 'error' => $e->getMessage(),
- ]);
- throw $e;
- }
- }
- /**
- * 从本地文件上传图片到春笋云
- */
- public function uploadFromFile(string $localPath): string
- {
- try {
- if (!file_exists($localPath)) {
- throw new \Exception("Local file does not exist: {$localPath}");
- }
- $fileName = basename($localPath);
- $uploadedUrl = $this->uploadToChunsun($localPath, $fileName);
- return $uploadedUrl;
- } catch (\Exception $e) {
- Log::error('Chunsun upload from file failed', [
- 'path' => $localPath,
- 'error' => $e->getMessage(),
- ]);
- throw $e;
- }
- }
- /**
- * 上传到春笋云
- */
- private function uploadToChunsun(string $filePath, string $fileName): string
- {
- $uploadUrl = config('services.chunsun.upload_url', env('CHUNSUN_UPLOAD_URL', 'https://crmapi.dcjxb.yunzhixue.cn'));
- try {
- $response = Http::timeout(60)
- ->attach('file', file_get_contents($filePath), $fileName)
- ->post($uploadUrl);
- if (!$response->successful()) {
- Log::error('Chunsun upload HTTP error', [
- 'status' => $response->status(),
- 'body' => $response->body(),
- 'url' => $uploadUrl,
- ]);
- throw new \Exception("Chunsun upload failed with status: {$response->status()}");
- }
- $data = $response->json();
- if (!isset($data['code']) || $data['code'] !== 200) {
- Log::error('Chunsun upload response error', [
- 'response' => $data,
- ]);
- throw new \Exception("Chunsun upload failed: " . ($data['message'] ?? 'Unknown error'));
- }
- if (!isset($data['data']['url'])) {
- throw new \Exception('No URL in Chunsun upload response');
- }
- Log::info('Chunsun upload successful', [
- 'file' => $fileName,
- 'url' => $data['data']['url'],
- ]);
- return $data['data']['url'];
- } catch (\Exception $e) {
- Log::error('Chunsun upload exception', [
- 'file' => $fileName,
- 'error' => $e->getMessage(),
- ]);
- throw $e;
- }
- }
- /**
- * 批量上传图片数组
- */
- public function uploadImagesFromArray(array $imageUrls): array
- {
- $uploadedUrls = [];
- foreach ($imageUrls as $index => $url) {
- $url = (string) $url;
- if ($url === '' || !preg_match('#^https?://#i', $url)) {
- // 非 http(s) URL 不处理(例如 data:、相对路径、本地路径),直接保留
- $uploadedUrls[$index] = $url;
- continue;
- }
- try {
- $uploadedUrls[$index] = $this->uploadFromUrl($url);
- } catch (\Exception $e) {
- Log::warning('Failed to upload image', [
- 'index' => $index,
- 'url' => $url,
- 'error' => $e->getMessage(),
- ]);
- // 保留原 URL 作为降级方案
- $uploadedUrls[$index] = $url;
- }
- }
- return $uploadedUrls;
- }
- /**
- * 根据 MIME 类型获取文件扩展名
- */
- private function getExtensionFromMimeType(string $mimeType): string
- {
- $extensions = [
- 'image/jpeg' => 'jpg',
- 'image/jpg' => 'jpg',
- 'image/png' => 'png',
- 'image/gif' => 'gif',
- 'image/webp' => 'webp',
- 'image/svg+xml' => 'svg',
- ];
- return $extensions[$mimeType] ?? 'jpg';
- }
- }
|