You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 02:34:57