質問 > 管理機能 > 画像のアップロードに失敗してしまう |
管理機能
スレッド表示 | 新しいものから | 前のトピック | 次のトピック | 下へ |
投稿者 | スレッド |
---|---|
r_yamada |
投稿日時: 2024/9/21 21:43
対応状況: −−−
|
常連 ![]() ![]() 登録日: 2024/9/2 居住地: 投稿: 39 |
画像のアップロードに失敗してしまう [EC-CUBE]4.3、新規インストール
[レンタルサーバ]ローカル環境 [OS]windows10 [PHP]8.3.11 [データベース]mysql8.0 [WEBサーバ]DockerDesktop4.33.1(Ubuntu) [ブラウザ]chrome [導入プラグインの有無]なし [カスタマイズの有無]なし [現象] お世話になっております。 コンテンツ管理に独自のメーカー管理というページを追加し、自身で追加した画像ファイルの入力フォーム(商品登録画面の商品画像と同じ構造)を作成したのですが、画像ファイル選択後のアップロード処理(登録ではなくドラッグアンドドロップした際の処理)にて Failed to load resource: the server responded with a status of 500 (Internal Server Error) のエラーが発生し、アップロードをすることができません。 こちらRouteやURLの設定に誤りがあると思い見直しているのですが特定できず、何が誤っているかご教示いただけないでしょうか? お手数ですがご回答いただけますと幸いです。 ・メーカー管理ページのURL http://localhost:8080/admin/content/maker/1/edit ・app\Customize\Controller\Admin\Content\MakerController.php namespace Customize\Controller\Admin\Content; use Eccube\Controller\AbstractController; use Eccube\Entity\Block; use Eccube\Entity\Master\DeviceType; use Eccube\Event\EccubeEvents; use Eccube\Event\EventArgs; use Eccube\Form\Type\Admin\BlockType; use Eccube\Repository\Master\DeviceTypeRepository; use Eccube\Util\CacheUtil; use Eccube\Util\StringUtil; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template; use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\Routing\Annotation\Route; use Twig\Environment; use Customize\Entity\Master\Maker; use Customize\Repository\Master\MakerRepository; use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Customize\Form\Extension\Admin\MakerType; use Customize\Entity\MakerImage; use Customize\Repository\Extension\MakerImageRepository; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; use Symfony\Component\HttpKernel\Exception\UnsupportedMediaTypeHttpException; use Symfony\Component\Routing\RouterInterface; class MakerController extends AbstractController { /** * @var MakerRepository */ protected $makerRepository; /** * @var MakerImageRepository * @param MakerImageRepository $makerImageRepository */ protected $makerImageRepository; public function __construct( MakerRepository $makerRepository, MakerImageRepository $makerImageRepository ) { $this->makerRepository = $makerRepository; } /** * メーカー管理ページを表示 * * @Route("/%eccube_admin_route%/content/maker", name="admin_content_maker", methods={"GET", "POST"}) * @Template("@admin/Content/maker.twig") */ public function index(Request $request) { $Makers = $this->makerRepository->getList(); $event = new EventArgs( [ 'Makers' => $Makers, ], $request ); $this->eventDispatcher->dispatch($event, EccubeEvents::ADMIN_CONTENT_BLOCK_INDEX_COMPLETE); return [ 'Makers' => $Makers, ]; } /** * @Route("/%eccube_admin_route%/content/maker/new", name="admin_content_maker_new", methods={"GET", "POST"}) * @Route("/%eccube_admin_route%/content/maker/{id}/edit", requirements={"id" = "\d+"}, name="admin_content_maker_edit", methods={"GET", "POST"}) * @Template("@admin/Content/maker_edit.twig") * */ public function edit(Request $request, RouterInterface $router, CacheUtil $cacheUtil, $id = null) { if ($id) { $Maker = $this->makerRepository->find($id); if (!$Maker) { throw new NotFoundHttpException(); } } else { $Maker = new \Customize\Entity\Master\Maker(); } $builder = $this->formFactory ->createBuilder(MakerType::class, $Maker); $event = new EventArgs( [ 'builder' => $builder, 'Maker' => $Maker, ], $request ); $this->eventDispatcher->dispatch($event, EccubeEvents::ADMIN_CONTENT_NEWS_EDIT_INITIALIZE); $form = $builder->getForm(); // ファイルの登録 $images = []; $MakerImages = $Maker->getMakerImage(); foreach ($MakerImages as $MakerImage) { $images[] = $MakerImage->getFileName(); } $form['images']->setData($images); $form->handleRequest($request); //更新時 if ($form->isSubmitted() && $form->isValid()) { $Maker = $form->getData(); $this->makerRepository->save($Maker); // 画像の登録 $add_images = $form->get('add_images')->getData(); foreach ($add_images as $add_image) { $MakerImage = new \Eccube\Entity\MakerImage(); $MakerImage ->setFileName($add_image) ->setProduct($Maker) ->setSortNo(1); $Maker->addMakerImage($MakerImage); $this->entityManager->persist($MakerImage); // 移動 $file = new File($this->eccubeConfig['eccube_temp_image_dir'].'/'.$add_image); $file->move($this->eccubeConfig['eccube_save_image_dir']); } // 画像の削除 $delete_images = $form->get('delete_images')->getData(); $fs = new Filesystem(); foreach ($delete_images as $delete_image) { $MakerImage = $this->makerImageRepository->findOneBy([ 'Maker' => $Maker, 'file_name' => $delete_image, ]); if ($MakerImage instanceof MakerImage) { $Product->removeMakerImage($MakerImage); $this->entityManager->remove($MakerImage); $this->entityManager->flush(); // 他に同じ画像を参照する商品がなければ画像ファイルを削除 if (!$this->makerImageRepository->findOneBy(['file_name' => $delete_image])) { $fs->remove($this->eccubeConfig['eccube_save_image_dir'].'/'.$delete_image); } } else { // 追加してすぐに削除した画像は、Entityに追加されない $fs->remove($this->eccubeConfig['eccube_temp_image_dir'].'/'.$delete_image); } } $this->entityManager->flush(); if ($maker_image = $request->request->all()['admin_product']['maker_image'] ?? []) { foreach ($maker_image as $sortNo => $filename) { $MakerImage = $this->makerImageRepository ->findOneBy([ 'file_name' => pathinfo($filename, PATHINFO_BASENAME), 'Maker' => $Maker, ]); if ($MakerImage !== null) { $MakerImage->setSortNo($sortNo); $this->entityManager->persist($MakerImage); } } $this->entityManager->flush(); } $event = new EventArgs( [ 'form' => $form, 'Maker' => $Maker, ], $request ); $this->eventDispatcher->dispatch($event, EccubeEvents::ADMIN_CONTENT_MAKER_EDIT_COMPLETE); $this->addSuccess('admin.common.save_complete', 'admin'); // キャッシュの削除 $cacheUtil->clearDoctrineCache(); return $this->redirectToRoute('admin_content_maker_edit', ['id' => $Maker->getId()]); } return [ 'form' => $form->createView(), 'Maker' => $Maker, ]; } /** * 画像アップロード時にリクエストされるメソッド. * * @see https://pqina.nl/filepond/docs/api/server/#process * @Route("/%eccube_admin_route%/content/maker/image/process", name="admin_maker_image_process", methods={"POST"}) */ public function imageProcess(Request $request) { if (!$request->isXmlHttpRequest() && $this->isTokenValid()) { throw new BadRequestHttpException(); } $images = $request->files->get('admin_maker'); $allowExtensions = ['gif', 'jpg', 'jpeg', 'png']; $files = []; if (count($images) > 0) { foreach ($images as $img) { foreach ($img as $image) { // ファイルフォーマット検証 $mimeType = $image->getMimeType(); if (0 !== strpos($mimeType, 'image')) { throw new UnsupportedMediaTypeHttpException(); } // 拡張子 $extension = $image->getClientOriginalExtension(); if (!in_array(strtolower($extension), $allowExtensions)) { throw new UnsupportedMediaTypeHttpException(); } $filename = date('mdHis').uniqid('_').'.'.$extension; $image->move($this->eccubeConfig['eccube_temp_image_dir'], $filename); $files[] = $filename; } } } $event = new EventArgs( [ 'images' => $images, 'files' => $files, ], $request ); $this->eventDispatcher->dispatch($event, EccubeEvents::ADMIN_PRODUCT_ADD_IMAGE_COMPLETE); $files = $event->getArgument('files'); return new Response(array_shift($files)); } /** * アップロード画像を取得する際にコールされるメソッド. * * @see https://pqina.nl/filepond/docs/api/server/#load * @Route("/%eccube_admin_route%/content/maker/image/load", name="admin_maker_image_load", methods={"GET"}) */ public function imageLoad(Request $request) { if (!$request->isXmlHttpRequest()) { throw new BadRequestHttpException(); } $dirs = [ $this->eccubeConfig['eccube_save_image_dir'], $this->eccubeConfig['eccube_temp_image_dir'], ]; foreach ($dirs as $dir) { if (strpos($request->query->get('source'), '..') !== false) { throw new NotFoundHttpException(); } $image = \realpath($dir.'/'.$request->query->get('source')); $dir = \realpath($dir); if (\is_file($image) && \str_starts_with($image, $dir)) { $file = new \SplFileObject($image); return $this->file($file, $file->getBasename()); } } throw new NotFoundHttpException(); } /** * アップロード画像をすぐ削除する際にコールされるメソッド. * * @see https://pqina.nl/filepond/docs/api/server/#revert * @Route("/%eccube_admin_route%/content/maker/image/revert", name="admin_maker_image_revert", methods={"DELETE"}) */ public function imageRevert(Request $request) { if (!$request->isXmlHttpRequest() && $this->isTokenValid()) { throw new BadRequestHttpException(); } $tempFile = $this->eccubeConfig['eccube_temp_image_dir'].'/'.$request->getContent(); if (is_file($tempFile) && stripos(realpath($tempFile), $this->eccubeConfig['eccube_temp_image_dir']) === 0) { $fs = new Filesystem(); $fs->remove($tempFile); return new Response(null, Response::HTTP_NO_CONTENT); } throw new NotFoundHttpException(); } } ・app\template\admin\Content\maker_edit.twig {# This file is part of EC-CUBE Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved. http://www.ec-cube.co.jp/ For the full copyright and license information, please view the LICENSE file that was distributed with this source code. #} {% extends '@admin/default_frame.twig' %} {% set menus = ['content', 'maker'] %} {% block title %}{{ 'admin.content.maker_management'|trans }}{% endblock %} {% block sub_title %}{{ 'admin.content.contents_management'|trans }}{% endblock %} {% form_theme form '@admin/Form/bootstrap_4_horizontal_layout.html.twig' %} {% block javascript %} <script> $(document).on('drop dragover', function(e) { e.preventDefault(); }); $(function() { // ファイルアップロード // see https://pqina.nl/filepond/ var inputFileElement = document.querySelector('input[type=file]'); {% if eccube_config.locale == 'ja' or eccube_config.locale == 'en' %} FilePond.setOptions(FilePondLocale_{{ eccube_config.locale }}); {% endif %} FilePond.setOptions({ server: { process: { url: '{{ path('admin_maker_image_process') }}', headers: { 'ECCUBE-CSRF-TOKEN': $('meta[name="eccube-csrf-token"]').attr('content'), 'X-Requested-With': 'XMLHttpRequest' } }, load: { url: '{{ path('admin_maker_image_load') }}?source=', headers: { 'X-Requested-With': 'XMLHttpRequest' } }, revert: { url: '{{ path('admin_maker_image_revert') }}', headers: { 'ECCUBE-CSRF-TOKEN': $('meta[name="eccube-csrf-token"]').attr('content'), 'X-Requested-With': 'XMLHttpRequest' } } } }); var pond = FilePond.create(inputFileElement, { allowFileTypeValidation: true, acceptedFileTypes: [ 'image/gif', 'image/png', 'image/jpeg' ], allowFileSizeValidation: true, maxFileSize: 10000000, maxFiles: 10, allowBrowse: true, allowDrop: true, allowReorder: true, labelIdle: '<i class="fa fa-cloud-upload fa-3x text-ec-lightGray mx-3 align-middle" aria-hidden="true" style="font-size: 40px"></i>{{ 'admin.common.drag_and_drop_image_description'|trans }}<span class="filepond--label-action">{{ 'admin.common.file_select'|trans }}</span>', styleItemPanelAspectRatio: 0.5625, // 保存されている画像のロード files: [ {% for image in form.images %} { source: '{{ image.vars.value }}', options: { type: 'local' } }, {% endfor %} // 追加してすぐの画像のロード. バリデーションエラーの場合など. {% for add_image in form.add_images %} { source: '{{ add_image.vars.value }}', options: { type: 'local' } }, {% endfor %} ] }); // 画像が追加されたら add_images にファイル名を追加する var proto_add = '{{ form_widget(form.add_images.vars.prototype) }}'; pond.on('processfile', function(error, file) { if (error) { console.log(error); } else { $('#upload-zone').append( $(proto_add.replace(/__name__/g, file.id)) .val(file.serverId) .addClass('add_images') ); } }); // 画像が削除されたら delete_images にファイル名を追加する var proto_del = '{{ form_widget(form.delete_images.vars.prototype) }}'; pond.on('removefile', function(error, file) { if (error) { console.log(error); } else { // file.serverId にはアップロードしたファイル名が格納される. if (file.serverId) { $('#upload-zone').append( $(proto_del.replace(/__name__/g, file.id)) .val(file.serverId) .addClass('del_images') ); } // 追加してすぐ削除した画像があれば削除する $('#upload-zone').find('#admin_maker_add_images_' + file.id).remove(); // 追加してすぐ削除した画像 $('#upload-zone').find('.add_images[value="' + file.filename + '"]').remove(); // 追加後, バリデーションエラーが発生した後に削除した画像 } }); pond.on('initfile', function() { $('#maker_image_error').hide(); }); pond.on('error', function(error, file) { var message = '{{ 'admin.common.upload_error'|trans }}'; if (error.main !== undefined) { message = `${error.main}: ${error.sub}`; } $('#maker_image_error') .show() .find('.form-error-message').text(message); // エラーメッセージが表示されてからプレビューエリアのエラーメッセージを非表示にする setTimeout(function() { $('.filepond--file-status').hide(); }, 300); }); // バリデーションエラーが出た場合に画像を保持するための hidden を追加しておく var proto_image = '{{ form_widget(form.images.vars.prototype) }}'; {% for image in form.images %} $('#upload-zone').append( $(proto_image.replace(/__name__/g, '{{ loop.index0 }}')) .val('{{ image.vars.value }}') .addClass('images') ); {% endfor %} {% for add_image in form.add_images %} $('#upload-zone').append( $('{{ form_widget(add_image) }}') .val('{{ add_image.vars.value }}') .addClass('add_images') ); {% endfor %} {% for delete_image in form.delete_images %} $('#upload-zone').append( $('{{ form_widget(delete_image) }}').addClass('del_images') ); {% endfor %} var confirmFormChange = function(form, target, modal) { var returnLink = form.find('input[type="hidden"][name*="return_link"]'), saveBtn = modal.find('a[data-action="save"]'), cancelBtn = modal.find('a[data-action="cancel"]'); modal.on('hidden.bs.modal', function() { returnLink.val(''); }); saveBtn.on('click', function() { returnLink.val($(this).data('return-link')); $(this).addClass('disabled'); form.submit(); }); target.on('click', function() { modal.find('.modal-body .screen-name').text($(this).attr('title')); modal.modal('show'); saveBtn.data('return-link', $(this).attr('href')); cancelBtn.attr('href', $(this).attr('href')); return false; }); }; confirmFormChange($('#form1'), $('a[data-action="confirm"]'), $('#confirmFormChangeModal')) }); </script> {% endblock javascript %} {% block main %} <form role="form" class="form-horizontal" name="form1" id="form1" method="post" action="?"> {{ form_widget(form._token) }} <div class="c-contentsArea__cols"> <div class="c-contentsArea__primaryCol"> <div class="c-primaryCol"> <div class="card rounded border-0 mb-4"> <div class="card-header"> <div class="row"> <div class="col-8"> <span class="card-title">{{ 'admin.content.maker.maker_registration'|trans }}</span></div> <div class="col-4 text-end"> <a data-bs-toggle="collapse" href="#makerForm" aria-expanded="true" aria-controls="makerForm"><i class="fa fa-lg fa-angle-up"></i></a></div> </div> </div> <div class="ec-cardCollapse collapse show" id="makerForm" style=""> <div class="card-body"> <div class="row"> <div class="col-3"> <span>{{ 'admin.content.maker.maker_name'|trans }}</span> <span class="badge bg-primary ms-1"> {{ 'admin.common.required'|trans }} </span> </div> <div class="col mb-2"> {{ form_widget(form.name) }} {{ form_errors(form.name) }} </div> </div> <div class="row"> <div class="col-3"> <span>{{ 'admin.content.maker.maker_production'|trans }}</span> </div> <div class="col mb-2"> {{ form_widget(form.production) }} {{ form_errors(form.production) }} </div> </div> <div class="row"> <div class="col-3"> <div class="d-inline-block" data-bs-toggle="tooltip" data-bs-placement="top" title="{{ 'tooltip.maker.image'|trans }}"> <span>{{ 'admin.maker.image'|trans }}</span> <i class="fa fa-question-circle fa-lg ms-1"></i> <br>{{ 'admin.maker.image_size'|trans }} </div> </div> <div class="col mb-2"> <p id="message"></p> <div id="upload-zone" class="rounded"> {{ form_widget(form.maker_image, { attr : { style : 'display:none;' } }) }} {{ form_errors(form.maker_image) }} </div><!-- /#upload-zone --> <span class="invalid-feedback" id="maker_image_error" style="display: none"> <span class="d-block"> <span class="form-error-icon badge bg-danger text-uppercase">{{ 'Error'|trans({}, 'validators') }}</span> <span class="form-error-message"></span> </span> </span> </div> </div> </div> </div> </div> </div> <div class="c-conversionArea"> <div class="c-conversionArea__container"> <div class="row justify-content-between align-items-center"> <div class="col-6"> <div id="ex-conversion-action" class="row align-items-center justify-content-end"> <div class="col-auto"> <button class="btn btn-ec-conversion px-5" type="submit">{{ 'admin.common.registration'|trans }}</button> </div> </div> </div> </div> </div> </div> </div> </div> </form> {% endblock %} ・app\Customize\Entity\Master\Maker.php namespace Customize\Entity\Master; use Customize\Entity\MakerImage; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\Mapping as ORM; if (!class_exists(Maker::class, false)) { /** * Maker * * @ORM\Table(name="mtb_maker") * @ORM\InheritanceType("SINGLE_TABLE") * @ORM\DiscriminatorColumn(name="discriminator_type", type="string", length=255) * @ORM\HasLifecycleCallbacks() * @ORM\Entity(repositoryClass="Customize\Repository\Master\MakerRepository") * @ORM\Cache(usage="NONSTRICT_READ_WRITE") */ class Maker extends \Eccube\Entity\Master\AbstractMasterEntity { /** * @var string|null * * @ORM\Column(name="production", type="string", length=255, nullable=true) */ private $production; /** * @var \Doctrine\Common\Collections\Collection * * @ORM\OneToMany(targetEntity="Customize\Entity\MakerImage", mappedBy="Maker", cascade={"remove"}) * @ORM\OrderBy({ * "sort_no"="ASC" * }) */ private $MakerImage; /** * Constructor */ public function __construct() { $this->MakerImage = new \Doctrine\Common\Collections\ArrayCollection(); } public function __clone() { $this->id = null; } /** * Set production * * @param string $production * * @return Maker */ public function setProduction($production) { $this->production = $production; return $this; } /** * Get production * * @return string */ public function getProduction() { return $this->production; } /** * Add makerImage. * * @param \Customize\Entity\MakerImage $makerImage * * @return Maker */ public function addMakerImage(MakerImage $makerImage) { $this->MakerImage[] = $makerImage; return $this; } /** * Remove makerImage. * * @param \Customize\Entity\MakerImage $makerImage * * @return boolean TRUE if this collection contained the specified element, FALSE otherwise. */ public function removeMakerImage(MakerImage $makerImage) { return $this->MakerImage->removeElement($makerImage); } /** * Get makerImage. * * @return \Doctrine\Common\Collections\Collection */ public function getMakerImage() { return $this->MakerImage; } } } |
k.nakayama |
投稿日時: 2024/9/24 8:09
対応状況: −−−
|
常連 ![]() ![]() 登録日: 2019/10/11 居住地: 投稿: 69 |
Re: 画像のアップロードに失敗してしまう ec-cubeのログやhttpdのログにエラー内容が出力されていないでしょうか?
※ログをスレッドに記載する場合は公開しない方が良い情報が含まれていないかご確認ください。
|
r_yamada |
投稿日時: 2024/9/24 13:41
対応状況: 解決済
|
常連 ![]() ![]() 登録日: 2024/9/2 居住地: 投稿: 39 |
Re: 画像のアップロードに失敗してしまう k.nakayama 様
ご返信ありがとうございます。 こちらec-cubeのログを確認したところ、useが足りていないことが原因と判明し、解決できました。 ありがとうございました。 |
スレッド表示 | 新しいものから | 前のトピック | 次のトピック | トップ |