// MyFolder / MyBundle / Entity / Name
<?php namespace MyFolder\MyBundle\Entity; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; /** * Table * * @ORM\Table(name="table") * @ORM\Entity */ class Table { /** * @var integer * * @ORM\Column(name="id", type="integer") * @ORM\Id */ private $id; /** * @var string * * @ORM\Column(name="name", type="string", length=255, nullable=true) */ private $filePath; } . /:
$ app / console doctrine:generate:エンティティMyFolder / MyBundle / Entity / Name
ゲッターとセッターが生成された後、ソナタに進みます。 したがって、ソナタファイルのコードは次のようになります。
// MyFolder / MyBundle / Admin / Name
<?php namespace MyFolder\MyBundle\Admin; use Sonata\AdminBundle\Admin\Admin; use Sonata\AdminBundle\Datagrid\ListMapper; use Sonata\AdminBundle\Datagrid\DatagridMapper; use Sonata\AdminBundle\Form\FormMapper; use Sonata\AdminBundle\Show\ShowMapper; class NameAdmin extends Admin { protected function configureFormFields(FormMapper $formMapper) { $formMapper ->add('name'); } protected function configureDatagridFilters(DatagridMapper $datagridMapper) { $datagridMapper ->add('name') } protected function configureListFields(ListMapper $listMapper) { $listMapper ->addIdentifier('name') } }
他に何もする必要はありません。 しばらく停止し、このリンク( github.com/weixiyen/jquery-filedrop)をたどります。 ここではライブラリに興味があります。jsファイルは1つしかないので、お見逃しなく:)。
だから。 ドラッグアンドドロップを実装する必要があるため、楽しみが始まります。実装しましょう。 これを行うには、MyBundle / Resources / view / Adminフォルダーで次の操作を行います(ない場合は、後でさらに混乱を作成します)。次の内容の小枝ファイル-sonata_admin_base_layout.html.twigを作成します。
// MyBundle / Resources / view / Admin / sonata_admin_base_layout.html.twig
{% extends 'SonataAdminBundle::standard_layout.html.twig' %} {% block stylesheets %} {{ parent() }} <link href="{{ asset('bundles/mybundle/css/admin/style.css') }}" rel="stylesheet" type="text/css" /> {% endblock %} {% block javascripts %} {{ parent() }} <script src="{{ asset('bundles/mybundle/js/admin/jquery.filedrop.js') }}"></script> <script src="{{ asset('bundles/mybundle/js/admin/js.fileDropBlock.js') }}"></script> <script src="{{ asset('bundles/mybundle/js/admin/js.fileLoadByDefault.js') }}"></script> <script src="{{ asset('bundles/mybundle/js/admin/init.js') }}"></script> {% endblock %}
config.ymlに移動して、メインのソナタテンプレートを再定義した後
// app / config / config.yml
sonata_admin: title: My Admin Panel templates: ## default global templates layout: MyFolderMyBundle:Admin:sonata_admin_base_layout.html.twig
そこで、ファイルを埋め込むことができるようにメインソナタテンプレートを再定義しました。 次の4行を自然に置き換えることができます。
<script src="{{ asset('bundles/mybundle/js/admin/jquery.filedrop.js') }}"></script> <script src="{{ asset('bundles/mybundle/js/admin/js.fileDropBlock.js') }}"></script> <script src="{{ asset('bundles/mybundle/js/admin/js.fileLoadByDefault.js') }}"></script> <script src="{{ asset('bundles/mybundle/js/admin/init.js') }}"></script>
これらのファイルは、実際には次のように私たちと共に生きています。
MyBundle / Resources / public / js / admin / jquery.filedrop.js
MyBundle / Resources / public / js / admin / js.fileDropBlock.js
MyBundle / Resources / public / js / admin / js.fileLoadByDefault.js
MyBundle / Resources / public / js / admin / js.init.js
すべてが正しいことに注意してください。ファイルを作成するには、パブリックフォルダーにadminフォルダーを作成することを強くお勧めします。
- js.fileDropBlock.js
- js.fileLoadByDefault.js
- init.js。
理解できるように、4の最初のファイルは以前にgitaからダウンロードしたものなので、恥ずかしがらずにadminフォルダーに入れてから、アセットを実行します。 コンソールに入力します
$ app / console asset:web --symlinkがすべて正しい場合はインストールします。パブリックフォルダーのコピーが/ bundle / mybundle /フォルダーに表示されるはずです。 運転しました。 次に、各ファイルについて順番に説明します。 したがって、ファイル番号1(js.fileDropBlock.js)とそのコード:
// MyBundle / Resources / public / js / admin / js.fileDropBlock.js
function fileDropBlock(block, type) { var allowType = { 'img': ['image/jpeg', 'image/png', 'image/gif'] }; block.filedrop({ url: '/upload-file', # url paramname: 'file', # . name input fallbackid: 'upload_button', maxfiles: 1, # - maxfilesize: 2, # mb # . error: function (err, file) { switch (err) { case 'BrowserNotSupported': console.log('Old browser'); break; case 'FileTooLarge': console.log('File Too Large'); break; case 'TooManyFiles': console.log('Only 1 file can be downloader'); break; case 'FileTypeNotAllowed': console.log('Wrong file type'); break; default: console.log('Some error'); } }, allowedfiletypes: allowType[type], # dragOver: function () { block.addClass('active-drag-block'); }, dragLeave: function () { block._removeClass('active-drag-block'); }, uploadFinished: function (i, file, response) { block.find('input[type="text"]').val(response.filePath); # } }) }
ファイルNo. 2(js.fileLoadByDefault.js)とそのコード:
// MyBundle / Resources / public / js / admin / js.LoadByDefault.js
var arrayType = { 'img': [ 'image/png', 'image/jpg', 'image/jpeg' ], 'pdf': [ 'application/pdf', 'application/x-pdf' ] }; function fileLoadByDefault(selector, type, block) { var input = document.getElementById(selector), formdata = false; input.click(); }
それほどではないですか? 少し後で彼が必要です。 最後に、ファイル番号3(init.js)とそのコード:
// MyBundle / Resources / public / js / admin / init.js
(function ($) { $(document).ready(function () { $.fn.uploadFile = function (type) { var blockText = { 'img': {'text': ['Drag Image File Here'], 'name': ['img'], 'id': ['imguploadform']} }; this.append('<p>' + blockText[type].text + '</p>'); this.append('<input type="file" class="upload-file" name="' + type + 'file" id="' + type + 'uploadform" data-type="'+ blockText[type].name +'">'); this.addClass('drag_n_drop--' + type + 'Path'); $('input', this).hide(); fileDropBlock(this, type); }; var imgBlock = $('div', 'div[id$="_coverPath"]'); imgBlock.uploadFile('img'); $('input[type="file"]').on("change", function () { var $_this = $(this), type = $_this.data('type'), reader, file; file = this.files[0]; if (window.FormData) { formdata = new FormData(); } if (window.FileReader) { reader = new FileReader(); reader.readAsDataURL(file); } if (formdata) { formdata.append("file", file); } if (!$.inArray(file.type, arrayType[type])) { $.ajax({ url: "/upload-file", type: "POST", data: formdata, processData: false, contentType: false, success: function (res) { var userData = jQuery.parseJSON(res); $_this.parent().find('input[type="text"]').val(userData.filePath); } }); } else { alert('Wrong type') } }); imgBlock.click(function () { fileLoadByDefault('imguploadform', 'img', this); }); }); })(jQuery);
何が起こっているのかを明確にし、部分的にコードを分析しましょう。 以前は、ページごとに1つの入力しかありませんでしたが、ドラッグアンドドロップ用の領域が必要です。
$.fn.uploadFile = function (type) { var blockText = { 'img': { 'text': ['Drag Image File Here'], 'name': ['img'], 'id': ['imguploadform'] } }; this.append('<p>' + blockText[type].text + '</p>'); this.append('<input type="file" class="upload-file" name="' + type + 'file" id="' + type + 'uploadform" data-type="'+ blockText[type].name +'">'); this.addClass('drag_n_drop--' + type + 'Path'); $('input', this).hide(); fileDropBlock(this, type); };
単一のパラメーターとして、特定の領域にロード(ドロップ)するドキュメントのタイプを取得する関数。
関数はそれを受け入れて、本質的に新しいhtmlコードを返しました。 テキストを含む段落が含まれます:
this.append('<p>' + blockText[type].text + '</p>');
ダウンロードボタンは、それでも重要な役割を果たします。
this.append('<input type="file" class="upload-file" name="' + type + 'file" id="' + type + 'uploadform" data-type="'+ blockText[type].name +'">');
要素にクラスを追加して、それが何であるかを理解します。
this.addClass('drag_n_drop--' + type + 'Path');
そして、すべての入力を非表示にします。
$('input', this).hide();
CSSカラーを追加します。
// MyBundle / Resources / public / css / style.css
.drag_n_drop--imgPath{ width: 150px; height: 100px; cursor: pointer; border: 2px solid #e0e0e0; background: #f9f9f9; }
最終的に、これらすべての操作の後、これに似たものを取得する必要があります。
もしそうなら、すべてが順調です。
さらにinit.jsファイル
そのようなコード:
var imgBlock = $('div', 'div[id$="_name"]'); # imgBlock.uploadFile('img'); # uploadFile
以下はそのような小さなコードです。
$('input[type="file"]').on("change", function () { # , var $_this = $(this), type = $_this.data('type'), reader, file; file = this.files[0]; # file if (window.FormData) { formdata = new FormData(); # ( js) } if (window.FileReader) { reader = new FileReader(); # reader.readAsDataURL(file); } if (formdata) { formdata.append("file", file); # } if (!$.inArray(file.type, arrayType[type])) { # $.ajax({ url: "/upload-file", # type: "POST", data: formdata, # processData: false, contentType: false, success: function (res) { var userData = jQuery.parseJSON(res); # $_this.parent().find('input[type="text"]').val(userData.filePath); # } }); } else { alert('Wrong type'); # alert } });
次に、コード:
imgBlock.click(function () { fileLoadByDefault('imguploadform', 'img', this); });
それは、その中に写真を投げるように設計されているディーバをクリックすると、その中のfileLoadByDefault関数には3つの引数があります。 1-タイプfileのid input'a。 2-アップロードするファイルのタイプ。 3-クリックが発生した親要素自体。
実際、ここで、注意深い読者は、実際には、コードが2つの読み込み方法を実装していることに気付くでしょう。 1つ目はドラッグ&ドロップ(ストリーミングの目的)で、2つ目はコンテナの歌姫をクリックして、Drup&Dropを対象とした標準形式のupload'aファイルを呼び出すことです。 基本的に2は副作用であり、このような素晴らしい副作用です。
私はあなたを動揺させたくありませんが、私たちは半分の仕事しかしませんでした...さらにもっと楽しく、今度はphpに行きましょう!
そのため、ファイルをドロップするか直接ダウンロードするかにかかわらず、あらゆるイベントの[/ upload-file]リンクを参照することを覚えています。
この場合のルートを決定する必要があります。
// MyFolder / MyBundle / Resourses / config / rounting.yml
my_file_upload: pattern: /upload-file defaults: { _controller: MyFolderMyBundle:Default:uploadFile }
[uploadFile]メソッドのコードを見てください。
// MyFolder / MuBundle / Contraller / Default.php
<?php namespace MyFolder\MyBundle\Controller; use Symfony\Component\HttpFoundation\File\File; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\File\UploadedFile; class DefaultController extends Controller { public function uploadFileAction() { $filename = $_FILES['file']; # $uploadPath = $this->upload($filename); # /** * . */ return null === $uploadPath ? new Response(json_encode(array( 'status' => 0, 'message' => 'Wrong file type' ) ) ) : new Response(json_encode(array( 'status' => 1, 'message' => $filename, # 'filePath' => $uploadPath # ) ) ); } private function getFoldersForUploadFile($type) { $fileType = $this->returnExistFileType($type); # if ($fileType !== null) { return array( 'root_dir' => $this->container->getParameter('upload_' . $fileType . '_root_directory'), # 'dir' => $this->container->getParameter('upload_' . $fileType . '_directory'), # ); } else { return null; } } # () private function returnExistFileType($type) { $typeArray = array( 'img' => array( 'image/png', 'image/jpg', 'image/jpeg', ), 'pdf' => array( 'application/pdf', 'application/x-pdf', ) ); foreach ($typeArray as $key => $value) { if (in_array($type, $value)) { return $key; } } return null; } # . , , private function upload($file) { $filePath = $this->getFoldersForUploadFile($file['type']); if (null === $this->getFileInfo($file['name']) || $filePath === null) { return null; } $pathInfo = $this->getFileInfo($file['name']); $path = $this->fileUniqueName() . '.' . $pathInfo['extension']; $this->uploadFileToFolder($file['tmp_name'], $path, $filePath['root_dir']); unset($file); return $filePath['dir'] . DIRECTORY_SEPARATOR . $path; } # ( ) private function getFileInfo($file) { return $file !== null ? (array)pathinfo($file) : null; } # private function fileUniqueName() { return sha1(uniqid(mt_rand(), true)); } # private function uploadFileToFolder($tmpFile, $newFileName, $rootFolder) { $e = new File($tmpFile); $e->move($rootFolder, $newFileName); }
結局のところ、悪魔はそれほどひどいものではありません。 おそらく私はいくつかのポイントを逃しました...しかし、あなた、親愛なる読者は、あなたの質問を書いて、コードとその最適化をコメントに自由に書くことができます。 実際、この記事では、ブートローダーをSymfonyに実装する最も簡単な方法を示しました。 当然、これらのメソッドはサービスに渡され、呼び出されるだけです。 すぐに行いますが、これは別の話です。
PSファイルをダウンロードするためのフォルダーへのパスはこのようになります
// app / config / config.yml
parameters: upload_img_root_directory: %kernel.root_dir%/../web/upload/img upload_img_directory: upload/img
アップロードフォルダーとimgフォルダーはその中にありません。作成する必要があります。
これらのフォルダが存在しない場合、これを行うメソッドを自由に作成することもできます。 それらに対する書き込み権限を忘れずに入れてください。