-
-
Notifications
You must be signed in to change notification settings - Fork 869
Description
Hello,
i created an api endpoint where i upload a file and i move it to a specific directory in my project. The thing is, the temp file of the uploaded file is not created hence, php cannot obtain its information when i try to move it. Here's the part of the error:
{
"type": "https:\/\/tools.ietf.org\/html\/rfc2616#section-10",
"title": "An error occurred",
"status": 500,
"detail": "The \"\/tmp\/php6c6dw1\" file does not exist or is not readable.",
"class": "Symfony\\Component\\Mime\\Exception\\InvalidArgumentException",
"trace": [
{
"namespace": "",
"short_class": "",
"class": "",
"type": "",
"function": "",
"file": "\/app\/vendor\/symfony\/mime\/FileinfoMimeTypeGuesser.php",
"line": 48,
"args": []
},
...I use a similar approch as the example of file upload as in the Symfony Documentation here: https://symfony.com/doc/current/controller/upload_file.html
Here is the logic of my controller:
#[Route(path: "/attachments", name: "tasks_attachments.")]
final class TasksAttachmentsController extends AbstractController
{
public function __construct(
private readonly EntityManagerInterface $entityManager
)
{
}
#[Route('/{task_id}', name: "add", methods: ["POST"])]
#[IsGranted("IS_AUTHENTICATED_FULLY")]
public function addNew(
#[MapEntity(mapping: ["task_id" => "id"])] Task $task,
FileUploader $fileUploader,
#[MapUploadedFile] UploadedFile $attachment
): JsonResponse
{
$uploadResult = $fileUploader->upload(
$attachment,
'/uploads/attachments'
);
$taskAttachment = new TaskAttachment();
$taskAttachment->setOwner($this->getUser())
->setOriginalName($uploadResult["originalName"])
->setName($uploadResult["fileName"]);
$task->addAttachment($taskAttachment);
$this->entityManager->persist($taskAttachment);
$this->entityManager->flush();
return $this->json($attachment, 200, [], [
'groups' => ['attachment:read']
]);
}
}The content of my FileUploader:
final readonly class FileUploader
{
public function __construct(
#[Autowire("%kernel.project_dir%")] private string $projectDir,
private SluggerInterface $slugger
)
{
}
/**
* Handles the uploading of a file to a specified directory.
*
* @param UploadedFile $file The file to upload.
* @param string $directory The directory where the file should be uploaded.
*
* @return array<"originalName"|"fileName", string> An associative array containing the original name of the file and the new file name.
*
*/
public function upload(UploadedFile $file, string $directory): array
{
$originalFilename = pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME);
$safeFilename = $this->slugger->slug($originalFilename);
$fileName = $safeFilename . '-' . uniqid() . '.' . $file->guessExtension();
$file->move($this->projectDir . $directory, $fileName);
return [
"originalName" => $originalFilename,
"fileName" => $fileName,
];
}
}I thought it is maybe a problem of permissions, in my containr while it was running, i set the ownership of the content of the tmp folder to that of the www-data user using these commands:
chown -R www-data:www-data /tmp
chmod -R u+rwX /tmp
The ownership changed, but i encounter the exact same error when i tried a file upload again. I did not mount the tmp directory on my host machine. The compose.yaml file content is basically the same as that of this repository.
Here is my Dockerfile content:
#syntax=docker/dockerfile:1
# Versions
FROM dunglas/frankenphp:1-php8.3 AS frankenphp_upstream
# The different stages of this Dockerfile are meant to be built into separate images
# https://docs.docker.com/develop/develop-images/multistage-build/#stop-at-a-specific-build-stage
# https://docs.docker.com/compose/compose-file/#target
# Base FrankenPHP image
FROM frankenphp_upstream AS frankenphp_base
WORKDIR /app
VOLUME /app/var/
# persistent / runtime deps
# hadolint ignore=DL3008
RUN apt-get update && apt-get install -y --no-install-recommends \
acl \
file \
gettext \
git \
&& rm -rf /var/lib/apt/lists/*
RUN set -eux; \
install-php-extensions \
@composer \
apcu \
intl \
opcache \
zip \
xsl \
;
# https://getcomposer.org/doc/03-cli.md#composer-allow-superuser
ENV COMPOSER_ALLOW_SUPERUSER=1
# Transport to use by Mercure (default to Bolt)
ENV MERCURE_TRANSPORT_URL=bolt:///data/mercure.db
ENV PHP_INI_SCAN_DIR=":$PHP_INI_DIR/app.conf.d"
###> recipes ###
###> doctrine/doctrine-bundle ###
RUN install-php-extensions pdo_pgsql
###< doctrine/doctrine-bundle ###
###< recipes ###
COPY --link frankenphp/conf.d/10-app.ini $PHP_INI_DIR/app.conf.d/
COPY --link --chmod=755 frankenphp/docker-entrypoint.sh /usr/local/bin/docker-entrypoint
COPY --link frankenphp/Caddyfile /etc/caddy/Caddyfile
ENTRYPOINT ["docker-entrypoint"]
HEALTHCHECK --start-period=60s CMD curl -f http://localhost:2019/metrics || exit 1
CMD [ "frankenphp", "run", "--config", "/etc/caddy/Caddyfile" ]
# Dev FrankenPHP image
FROM frankenphp_base AS frankenphp_dev
ENV APP_ENV=dev
ENV XDEBUG_MODE=off
ENV FRANKENPHP_WORKER_CONFIG=watch
RUN mv "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini"
RUN set -eux; \
install-php-extensions \
xdebug \
;
COPY --link frankenphp/conf.d/20-app.dev.ini $PHP_INI_DIR/app.conf.d/
CMD [ "frankenphp", "run", "--config", "/etc/caddy/Caddyfile", "--watch" ]
# Prod FrankenPHP image
FROM frankenphp_base AS frankenphp_prod
ENV APP_ENV=prod
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
COPY --link frankenphp/conf.d/20-app.prod.ini $PHP_INI_DIR/app.conf.d/
# prevent the reinstallation of vendors at every changes in the source code
COPY --link composer.* symfony.* ./
RUN set -eux; \
composer install --no-cache --prefer-dist --no-dev --no-autoloader --no-scripts --no-progress
# copy sources
COPY --link . ./
RUN rm -Rf frankenphp/
RUN set -eux; \
mkdir -p var/cache var/log; \
composer dump-autoload --classmap-authoritative --no-dev; \
composer dump-env prod; \
composer run-script --no-dev post-install-cmd; \
chmod +x bin/console; sync;