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

TYPO3前端环境下FAL资源引用与属性值的上传及更新问题

TYPO3 FAL文件引用更新问题:存在则更新元属性,不存在则新建

当前处理TYPO3包含FAL图片的记录更新时,新增文件能正常生成FileReference,但更新操作会创建新的引用而非修改现有对象,需要实现存在FileReference则更新其元属性,不存在则新建的逻辑。

现有更新操作代码

$obj = $this->mediaAlbumRepository->findByUid(GeneralUtility::_GP('album'));
$obj->setTitle(GeneralUtility::_GP('title'));
$obj->setDescription(GeneralUtility::_GP('description'));
$obj->setWebdescription(GeneralUtility::_GP('webdescription'));
$obj->setType(GeneralUtility::_GP('type'));
$obj->setDatetime(new \DateTime());
$obj->setGalleryOwner($this->user['uid']);

$assetsMetaData = GeneralUtility::_GP('imgMetaData');

$utilityObj = GeneralUtility::makeInstance(UploadAssetsProviderUtility::class);
$fileObj = $utilityObj->processAssets($_FILES, $assetsMetaData, $uploadFolderId);

$fileObjStorage = GeneralUtility::makeInstance(ObjectStorage::class);
foreach($fileObj as $item) {            
    $fileObjStorage->attach($item);
}
if(GeneralUtility::_GP('type') == 'static') {
    $obj->setFiles($fileObjStorage);
}

$this->mediaAlbumRepository->update($obj);

UploadAssetsProviderUtility中的uploadFile方法代码

/**
 * Create file reference object
 *
 * @param UploadedFile $fileImage
 * @param Folder $uploadFolder
 * @param String $uploadFolderId
 * @param Array $metainfo
 * @return FileReference $fileReference
 */
protected function uploadFile($fileImage, $uploadFolder, $uploadFolderId, $fileMeta = []): FileReference
{
    [$storageId, $storagePath] = explode(':', $uploadFolderId, 2);
    $storage = $this->resourceFactory->getStorageObject($storageId);
    $fileReference = GeneralUtility::makeInstance(
        FileReference::class,
        $assetProp,
        $this->resourceFactory
    );

    if(is_array($fileImage)) {
        $file = $storage->addFile(
            $fileImage['tmp_name'],
            $uploadFolder,
            $fileImage['name']
        );
        $assetProp = [
            'uid_local' => $file->getUid(),
            'uid_foreign' => StringUtility::getUniqueId('NEW_'),
            'uid' => StringUtility::getUniqueId('NEW_'),
            'crop' => null,
        ];
        $metaTitle = $fileImage['falMetaData']['title'] ? $fileImage['falMetaData']['title'] : $fileImage['name'];
        $metaAlt = $fileImage['falMetaData']['alt'] ? $fileImage['falMetaData']['alt'] : $fileImage['name'];
        $metaLink = $fileImage['falMetaData']['link'] ? $fileImage['falMetaData']['link'] : '';
        $metaDescription = $fileImage['falMetaData']['description'] ? $fileImage['falMetaData']['description'] : '';

        $fileReference->setOriginalResource($file);
    } else {
        // here $metainfo->uid has existing Filereference UID if already exist and find Filereference object
        $fileImage = $this->resourceFactory->getFileReferenceObject($metainfo->uid);

        $properies = $fileImage->getReferenceProperties();
        $metaTitle = $fileMeta['falMetaData']['title'] ? $fileMeta['falMetaData']['title'] : $fileMeta['name'];
        $metaAlt = $fileMeta['falMetaData']['alt'] ? $fileMeta['falMetaData']['alt'] : $fileMeta['name'];
        $metaLink = $fileMeta['falMetaData']['link'] ? $fileMeta['falMetaData']['link'] : '';
        $metaDescription = $fileMeta['falMetaData']['description'] ? $fileMeta['falMetaData']['description'] : '';

        $fileReference->setUidLocal($properies['uid_local']);
    }

    $fileReference->setTitle($metaTitle);
    $fileReference->setAlternative($metaAlt);
    $fileReference->setDescription($metaDescription);
    $fileReference->setLink($metaLink);        
    $fileReference->setTableLocal('sys_file');
    $fileReference->setTablenames($this->foreignTable);

    return $fileReference;
}

问题核心与修复方案

核心问题

更新分支中,代码重新实例化了新的FileReference对象,而非直接修改已加载的原有引用对象,导致保存时生成新记录而非更新旧记录。

修复步骤

  1. 区分新建/更新逻辑,直接操作原对象
    处理已有引用时,直接使用加载的原FileReference对象更新属性,不再新建实例。
  2. 修正变量顺序与取值逻辑
    调整$assetProp定义位置,避免实例化时变量未定义;修复元数据取值的变量混淆问题。
  3. 保留原有引用的默认值
    更新元属性时,若前端未传递新值,保留原有引用的属性值,避免覆盖为空。

修改后的uploadFile方法

/**
 * 创建或更新文件引用对象
 *
 * @param mixed $fileImage 新上传的文件数组或已有引用的UID
 * @param Folder $uploadFolder
 * @param string $uploadFolderId
 * @param array $fileMeta 元数据
 * @return FileReference
 */
protected function uploadFile($fileImage, $uploadFolder, $uploadFolderId, $fileMeta = []): FileReference
{
    [$storageId, $storagePath] = explode(':', $uploadFolderId, 2);
    $storage = $this->resourceFactory->getStorageObject($storageId);
    $fileReference = null;

    // 处理新上传文件:新建FileReference
    if (is_array($fileImage)) {
        $file = $storage->addFile(
            $fileImage['tmp_name'],
            $uploadFolder,
            $fileImage['name']
        );
        $assetProp = [
            'uid_local' => $file->getUid(),
            'uid_foreign' => StringUtility::getUniqueId('NEW_'),
            'uid' => StringUtility::getUniqueId('NEW_'),
            'crop' => null,
        ];
        $fileReference = GeneralUtility::makeInstance(
            FileReference::class,
            $assetProp,
            $this->resourceFactory
        );
        $fileReference->setOriginalResource($file);

        // 提取元数据,无值则用文件名
        $metaTitle = $fileImage['falMetaData']['title'] ?? $fileImage['name'];
        $metaAlt = $fileImage['falMetaData']['alt'] ?? $fileImage['name'];
        $metaLink = $fileImage['falMetaData']['link'] ?? '';
        $metaDescription = $fileImage['falMetaData']['description'] ?? '';
    } else {
        // 处理已有引用:加载原对象并更新属性
        $fileReference = $this->resourceFactory->getFileReferenceObject($fileImage);
        
        // 提取元数据,无值则保留原引用的属性
        $metaTitle = $fileMeta['falMetaData']['title'] ?? $fileReference->getTitle();
        $metaAlt = $fileMeta['falMetaData']['alt'] ?? $fileReference->getAlternative();
        $metaLink = $fileMeta['falMetaData']['link'] ?? $fileReference->getLink();
        $metaDescription = $fileMeta['falMetaData']['description'] ?? $fileReference->getDescription();
    }

    // 统一设置元属性
    $fileReference->setTitle($metaTitle);
    $fileReference->setAlternative($metaAlt);
    $fileReference->setDescription($metaDescription);
    $fileReference->setLink($metaLink);        
    $fileReference->setTableLocal('sys_file');
    $fileReference->setTablenames($this->foreignTable);

    return $fileReference;
}

主逻辑补充说明

确保$assetsMetaData传递了已有FileReference的UID,让uploadFile能正确识别更新操作;同时ObjectStorage要包含所有需要保留的引用(更新后的+新增的),避免丢失未修改的原有引用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 18:08:10