在 Symfony 4 应用程序中,您将用户上传的内容存储在哪里?
Where do you store user uploaded content within a Symfony 4 application?
我的站点中有一个部分,用户可以在其中上传自己的个人资料图片,这些图片存储在输出目录中并在数据库中进行跟踪,如下所示:
$form = $this->createForm(ProfileUpdateForm::class);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid())
{
$user = $this->getUser();
$firstname = $form->get('firstname')->getData();
$lastname = $form->get('lastname')->getData();
$picture = $form->get('profilepicture')->getData();
if($picture == null)
{
$user
->setFirstName($firstname)
->setLastName($lastname);
}
else
{
$originalFilename = pathinfo($picture->getClientOriginalName(), PATHINFO_FILENAME);
// this is needed to safely include the file name as part of the URL
$safeFilename = strtolower(str_replace(' ', '', $originalFilename));
$newFilename = $safeFilename.'-'.uniqid().'.'.$picture->guessExtension();
try {
$picture->move(
'build/images/user_profiles/',
$newFilename
);
} catch (FileException $e) {
$this->addFlash("error", "Something happened with the file upload, try again.");
return $this->redirect($request->getUri());
}
// updates the 'picture' property to store the image file name
// instead of its contents
$user
->setProfilePicture($newFilename)
->setFirstName($firstname)
->setLastName($lastname);
}
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($user);
$entityManager->flush();
$this->addFlash("success", "Your profile was updated!");
return $this->redirectToRoute('account');
}
return $this->render('account/profile.html.twig', [
'profileform' => $form->createView()
]);
我发现的那个问题是,每次我编译我的(本地)项目时,图像都会被删除(因为 public/build 目录是通过删除和重新创建构建的)。
如果我没记错的话,部署不也是这样吗?如果是这样,这是上传图片的正确方法吗?正确的做法是什么?
我不确定为什么,但您的 public/
目录不应该被删除。
如果您使用的是 Webpack Encore,那么 public/build/
内容会在您编译资产时被删除并重新创建。但不是 public/
本身。
对于上传,我们创建 public/upload/
目录。
然后,大多数时候,我们会设置一些全局变量,这样我们就可以只保存文件名。
config/packages/twig.yaml
中 Twig 的全局变量 "root" 将在您的 public/
目录中
twig:
globals:
app_ul_avatar: '/upload/avatar/'
app_ul_document: '/upload/document/'
以及 config/services.yaml
中控制器、存储库等的全局变量
parameters:
app_ul_avatar: '%kernel.root_dir%/../public/upload/avatar/'
app_ul_document: '%kernel.root_dir%/../public/upload/document/'
这很方便,因为正如我刚才所说,您只需将文件名保存在数据库中。
这意味着,如果你有一个 public/upload/img/
文件夹,并且还想生成缩略图,你可以创建 public/upload/img/thumbnail/
并且你的数据库中没有任何改变,你也不必保存一条额外的路径。
只需创建一个新的全局 app_ul_img_thumbnail
,就大功告成了。
那么你所要做的就是在你需要的时候调用你的全局变量,并与文件名联系:
在 Twig 中:
{{ app_ul_avatar~dbResult.filename }}
或者在控制器中:
$this->getParameter('app_ul_avatar').$dbResult->getFilename();
我的站点中有一个部分,用户可以在其中上传自己的个人资料图片,这些图片存储在输出目录中并在数据库中进行跟踪,如下所示:
$form = $this->createForm(ProfileUpdateForm::class);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid())
{
$user = $this->getUser();
$firstname = $form->get('firstname')->getData();
$lastname = $form->get('lastname')->getData();
$picture = $form->get('profilepicture')->getData();
if($picture == null)
{
$user
->setFirstName($firstname)
->setLastName($lastname);
}
else
{
$originalFilename = pathinfo($picture->getClientOriginalName(), PATHINFO_FILENAME);
// this is needed to safely include the file name as part of the URL
$safeFilename = strtolower(str_replace(' ', '', $originalFilename));
$newFilename = $safeFilename.'-'.uniqid().'.'.$picture->guessExtension();
try {
$picture->move(
'build/images/user_profiles/',
$newFilename
);
} catch (FileException $e) {
$this->addFlash("error", "Something happened with the file upload, try again.");
return $this->redirect($request->getUri());
}
// updates the 'picture' property to store the image file name
// instead of its contents
$user
->setProfilePicture($newFilename)
->setFirstName($firstname)
->setLastName($lastname);
}
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($user);
$entityManager->flush();
$this->addFlash("success", "Your profile was updated!");
return $this->redirectToRoute('account');
}
return $this->render('account/profile.html.twig', [
'profileform' => $form->createView()
]);
我发现的那个问题是,每次我编译我的(本地)项目时,图像都会被删除(因为 public/build 目录是通过删除和重新创建构建的)。
如果我没记错的话,部署不也是这样吗?如果是这样,这是上传图片的正确方法吗?正确的做法是什么?
我不确定为什么,但您的 public/
目录不应该被删除。
如果您使用的是 Webpack Encore,那么 public/build/
内容会在您编译资产时被删除并重新创建。但不是 public/
本身。
对于上传,我们创建 public/upload/
目录。
然后,大多数时候,我们会设置一些全局变量,这样我们就可以只保存文件名。
config/packages/twig.yaml
中 Twig 的全局变量 "root" 将在您的 public/
目录中
twig:
globals:
app_ul_avatar: '/upload/avatar/'
app_ul_document: '/upload/document/'
以及 config/services.yaml
parameters:
app_ul_avatar: '%kernel.root_dir%/../public/upload/avatar/'
app_ul_document: '%kernel.root_dir%/../public/upload/document/'
这很方便,因为正如我刚才所说,您只需将文件名保存在数据库中。
这意味着,如果你有一个 public/upload/img/
文件夹,并且还想生成缩略图,你可以创建 public/upload/img/thumbnail/
并且你的数据库中没有任何改变,你也不必保存一条额外的路径。
只需创建一个新的全局 app_ul_img_thumbnail
,就大功告成了。
那么你所要做的就是在你需要的时候调用你的全局变量,并与文件名联系:
在 Twig 中:
{{ app_ul_avatar~dbResult.filename }}
或者在控制器中:
$this->getParameter('app_ul_avatar').$dbResult->getFilename();