I need to make backup of certain Media Files.
They are provided as array. Code make new UUID, copy properties and saves to database. This is working. The problem is I can't upload file to that database entry. I've got error:
Object { status: "500", code: "CONTENT__MEDIA_DUPLICATED_FILE_NAME", title: "Internal Server Error"...
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;
}
I changed filename name, what's the problem?
When you use the original media related services, you'll find that the media
entity is initially persisted without the fileName
and other meta data info about the file. The persistFileToMedia
method then checks whether a media entity with the file name you're trying to upload already exists. Since you're persisting one with that exact name just prior, you'll run into that exception.
To make life a little bit easier, you can also use the clone
method of the repository, to create a copy. You can define a behavior for the clone, where you can override certain properties. Finally you'll have to execute the clone command within a system-scoped context, as normally you wouldn't be allowed to directly write the fileName
property, since that would normally be the job of the file saver abstraction, e.g. that method persistFileToMedia
you're calling.
Example:
// to write fileName and other metadata directly, you need the system scope
$newMediaId = $context->scope(Context::SYSTEM_SCOPE, function (Context $context) use ($oldMediaId): string {
$behavior = new CloneBehavior([
'mimeType' => null,
'fileExtension' => null,
'uploadedAt' => null,
'fileName' => null,
'fileSize' => null,
'metaData' => null,
]);
$newMediaId = Uuid::randomHex();
$this->mediaRepository->clone($oldMediaId, $context, $newMediaId, $behavior);
return $newMediaId;
});
$this->fileSaver->persistFileToMedia(
$mediaFile,
$originalFileName . '_old',
$newMediaId,
$context
);