Symfony 6 REST API开发:实现图片列表与单图查询接口
Symfony 6 REST API 图片上传与接口实现
1. 创建图片实体
先定义Image实体,用于存储图片的核心信息到数据库:
// src/Entity/Image.php namespace App\Entity; use Doctrine\ORM\Mapping as ORM; #[ORM\Entity] #[ORM\Table(name: 'images')] class Image { #[ORM\Id] #[ORM\GeneratedValue] #[ORM\Column(type: 'integer')] private ?int $id = null; #[ORM\Column(type: 'string', length: 255)] private ?string $filename = null; #[ORM\Column(type: 'datetime_immutable')] private ?\DateTimeImmutable $createdAt = null; public function __construct() { $this->createdAt = new \DateTimeImmutable(); } // Getters & Setters public function getId(): ?int { return $this->id; } public function getFilename(): ?string { return $this->filename; } public function setFilename(string $filename): self { $this->filename = $filename; return $this; } public function getCreatedAt(): ?\DateTimeImmutable { return $this->createdAt; } }
执行数据库迁移生成对应表:
php bin/console make:migration php bin/console doctrine:migrations:migrate
2. 控制器实现完整接口
以下是包含上传、获取所有图片、获取单张图片的控制器代码,满足需求的两个核心接口:
// src/Controller/ImageController.php namespace App\Controller; use App\Entity\Image; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\BinaryFileResponse; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\String\Slugger\SluggerInterface; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; #[Route('/api/images', name: 'api_images_')] class ImageController extends AbstractController { private string $imageStorageDir; public function __construct(string $kernelProjectDir) { // 定义图片存储目录 $this->imageStorageDir = $kernelProjectDir . '/public/uploads/images/'; // 自动创建目录(如果不存在) if (!is_dir($this->imageStorageDir)) { mkdir($this->imageStorageDir, 0755, true); } } // 上传PNG图片(可选补充:需先上传才能有数据查询) #[Route(methods: ['POST'])] public function upload(Request $request, SluggerInterface $slugger, EntityManagerInterface $em): JsonResponse { $file = $request->files->get('image'); if (!$file) { return new JsonResponse(['error' => '未提供图片文件'], Response::HTTP_BAD_REQUEST); } // 验证是否为PNG格式 if ($file->getMimeType() !== 'image/png') { return new JsonResponse(['error' => '仅支持PNG格式图片'], Response::HTTP_UNSUPPORTED_MEDIA_TYPE); } // 生成安全的文件名,避免冲突 $originalName = pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME); $safeName = $slugger->slug($originalName); $newFilename = $safeName . '-' . uniqid() . '.' . $file->guessExtension(); try { // 移动文件到存储目录 $file->move($this->imageStorageDir, $newFilename); } catch (\Exception $e) { return new JsonResponse(['error' => '图片上传失败'], Response::HTTP_INTERNAL_SERVER_ERROR); } // 保存文件名到数据库 $image = new Image(); $image->setFilename($newFilename); $em->persist($image); $em->flush(); return new JsonResponse([ 'id' => $image->getId(), 'filename' => $image->getFilename(), 'access_url' => $this->generateUrl('api_images_show', ['id' => $image->getId()], UrlGeneratorInterface::ABSOLUTE_URL) ], Response::HTTP_CREATED); } // 获取所有图片信息 #[Route(methods: ['GET'])] public function listAll(EntityManagerInterface $em): JsonResponse { $images = $em->getRepository(Image::class)->findAll(); $responseData = []; foreach ($images as $image) { $responseData[] = [ 'id' => $image->getId(), 'filename' => $image->getFilename(), 'created_at' => $image->getCreatedAt()->format('Y-m-d H:i:s'), 'access_url' => $this->generateUrl('api_images_show', ['id' => $image->getId()], UrlGeneratorInterface::ABSOLUTE_URL) ]; } return new JsonResponse($responseData); } // 获取指定ID的图片内容 #[Route('/{id}', name: 'show', methods: ['GET'])] public function show(int $id, EntityManagerInterface $em): Response { $image = $em->getRepository(Image::class)->find($id); if (!$image) { return new JsonResponse(['error' => '图片不存在'], Response::HTTP_NOT_FOUND); } $filePath = $this->imageStorageDir . $image->getFilename(); if (!file_exists($filePath)) { return new JsonResponse(['error' => '图片文件已丢失'], Response::HTTP_NOT_FOUND); } // 返回图片文件,设置正确的Content-Type $response = new BinaryFileResponse($filePath); $response->headers->set('Content-Type', 'image/png'); return $response; } }
3. 关键注意事项
- 确保
public/uploads/images目录拥有服务器可写权限,部署时可通过chmod -R 755 public/uploads设置。 - 生产环境建议使用云存储(如阿里云OSS、AWS S3)替代本地存储,避免服务器容量瓶颈和单点故障。
- 可添加JWT等认证机制,限制未授权用户的上传和访问行为。
- 如需限制图片大小,可在上传接口中添加
$file->getSize()的校验逻辑。
内容的提问来源于stack exchange,提问作者krisforerr4567
相关产品推荐
相关产品推荐

