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

Shopware 6 PHP克隆媒体文件:重命名后仍遇文件名重复错误

问题描述

需要备份指定媒体文件(以数组传入),代码已实现生成新UUID、复制属性并保存到数据库,但上传文件到对应数据库条目时失败,报错:
Object { status: "500", code: "CONTENT__MEDIA_DUPLICATED_FILE_NAME", title: "Internal Server Error"...}
已尝试修改文件名,但问题依旧,相关PHP代码如下:

function makeBackup(array $images, Context $context) :bool
{
    foreach ($images as $i) {
        $uuid = Uuid::randomHex();
        $path = $this->urlGeneratorInterface->getRelativeMediaUrl($i);
        try {
            $this->publicFileSystem->read($path);
            $stream = $this->publicFileSystem->readStream($path);
            $metaData = stream_get_meta_data($stream);
            $oldFileNameWithPath = $metaData['uri'];
        }catch (UnableToReadFile $e){
            echo "[ERROR] File $path does not exists. Continuing.\n";
            continue;
        }

        $mimeType = mime_content_type($oldFileNameWithPath);
        $fileExtension = pathinfo($oldFileNameWithPath, PATHINFO_EXTENSION);
        $fileSize = filesize($oldFileNameWithPath);
        $fileName = pathinfo($oldFileNameWithPath, PATHINFO_FILENAME) . '_old.' . $fileExtension;
        $mediaFile = new MediaFile($fileName, $mimeType, $fileExtension, $fileSize);

        $backupMediaData = [
            'id' => $uuid,
            'fileName' => $i->getFileName()."_old",
            'mimeType' => $i->getMimeType(),
            'fileSize' => $i->getFileSize(),
            // 'mediaFolderId' => $media->getMediaFolderId(),
            'createdAt' => $i->getCreatedAt(),
            'updatedAt' => $i->getUpdatedAt(),
            'alt' => $i->getAlt(),
            'title' => $i->getTitle()."_old",
        ];
        $this->mediaRepository->create([$backupMediaData], $context);

       $this->fileSaver->persistFileToMedia(
            $mediaFile,
            pathinfo($oldFileNameWithPath, PATHINFO_FILENAME),
            $uuid,
            $context
        );
    }
    return true;
}
问题定位

错误码CONTENT__MEDIA_DUPLICATED_FILE_NAME明确指向文件名重复,核心问题出在两处:

  1. 上传方法传入了原文件名
    调用persistFileToMedia时,第二个参数传的是pathinfo($oldFileNameWithPath, PATHINFO_FILENAME)——也就是未加_old后缀的原文件名,这导致实际上传时还是用了和原文件一样的名称,自然触发重复错误。

  2. 数据库记录与上传文件名不一致
    backupMediaData中的fileName是$i->getFileName()."_old",而$mediaFile的文件名是原文件名_old.后缀。如果原文件对象的getFileName()包含后缀,这里会生成xxx.jpg_old的格式,和$mediaFile的xxx_old.jpg格式冲突,同时也可能和其他备份文件重名。

修复方案

1. 统一文件名规则

确保数据库记录的文件名和上传时使用的文件名逻辑一致,避免格式冲突。

2. 修正上传方法的参数

将persistFileToMedia的第二个参数改为修改后的唯一文件名(不带后缀,多数媒体库会自动根据MediaFile的后缀拼接)。

修改后的关键代码片段:

// 统一生成带_old后缀的纯文件名(不带扩展名)
$baseFileName = pathinfo($oldFileNameWithPath, PATHINFO_FILENAME) . '_old';
// 生成完整文件名(带扩展名)
$fileName = $baseFileName . '.' . $fileExtension;
$mediaFile = new MediaFile($fileName, $mimeType, $fileExtension, $fileSize);

$backupMediaData = [
    'id' => $uuid,
    'fileName' => $baseFileName, // 和上传逻辑保持一致,若系统要求带后缀则改为$fileName
    'mimeType' => $i->getMimeType(),
    'fileSize' => $i->getFileSize(),
    // 'mediaFolderId' => $media->getMediaFolderId(),
    'createdAt' => $i->getCreatedAt(),
    'updatedAt' => $i->getUpdatedAt(),
    'alt' => $i->getAlt(),
    'title' => $i->getTitle()."_old",
];
$this->mediaRepository->create([$backupMediaData], $context);

// 传入修改后的纯文件名,确保上传时使用唯一名称
$this->fileSaver->persistFileToMedia(
    $mediaFile,
    $baseFileName,
    $uuid,
    $context
);

额外注意事项

  • 若批量备份的文件中存在原文件名已带_old的情况,建议进一步添加UUID后缀(比如$baseFileName = pathinfo(...) . '_old_' . $uuid),彻底避免重复。
  • 确认persistFileToMedia方法的参数要求,部分库可能要求第二个参数是完整文件名,需根据实际情况调整。

内容的提问来源于stack exchange,提问作者user21851666

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 00:27:45