Dropzone کتابخانه ای با سورس رایگان برای آپلود بصورت drog and drop که بسیار محبوب است که پس از آپلود یک پیش نمایش از عکس به شما نمایش می دهد.
در ابتدا یک پروژه لاراول ایجاد می کنیم:
laravel new upload
سپس در فایل env اطلاعات دیتابیس خود را پر می کنیم.
در مرحله بعد فایل dropzone.css و dropzone.js را از cdnjs.com دانلود و در دایرکتوریهای public/css و public/js قرار دهید و bootstrap 4 css را در public/css با نام bootstrap قرار دهید و در دایرکتوری public/css فایل custom.css را می سازیم. Dropzone از jQuery استفاده می کند بنابراین آنرا دانلود و با نام jquery.js در پوشه public/js قرار می دهیم.
چهار روت برای آپلود فایل در routes/web.php ایجاد می کنیم:
Route::get('/', 'UploadImagesController@create');
Route::post('/images-save', 'UploadImagesController@store');
Route::post('/images-delete', 'UploadImagesController@destroy');
Route::get('/images-show', 'UploadImagesController@index');
یک فایل main.blade.php در دایرکتوری resources/view ایجاد می کنیم:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Uploading images in Laravel with DropZone</title>
<link rel="stylesheet" href="{{ url('/css/bootstrap.css') }}">
@yield('head')
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<a class="navbar-brand" href="{{ url('/') }}">Upload</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav"
aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" href="{{ url('/') }}">Upload Images</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ url('/images-show') }}">View Uploaded Files</a>
</li>
</ul>
</div>
</nav>
<div class="container-fluid">
@yield('content')
</div>
@yield('js')
</body>
</html>
فایل دیگری با نام upload.blade.php در resources/views ایجاد می کنیم.
@extends('main')
@section('head')
<link rel="stylesheet" href=" url('/css/dropzone.css') ">
<link rel="stylesheet" href=" url('/css/custom.css') ">
@endsection
@section('js')
<script src=" url('/js/jquery.js') "></script>
<script src=" url('/js/dropzone.js') "></script>
<script src=" url('/js/dropzone-config.js') "></script>
@endsection
@section('content')
<div class="row">
<div class="col-sm-10 offset-sm-1">
<h2 class="page-heading">Upload your Images <span id="counter"></span></h2>
<form method="post" action=" url('/images-save') "
enctype="multipart/form-data" class="dropzone" id="my-dropzone">
csrf_field()
<div class="dz-message">
<div class="col-xs-8">
<div class="message">
<p>Drop files here or Click to Upload</p>
</div>
</div>
</div>
<div class="fallback">
<input type="file" name="file" multiple>
</div>
</form>
</div>
</div>
<div id="preview" style="display: none;">
<div class="dz-preview dz-file-preview">
<div class="dz-image"><img data-dz-thumbnail /></div>
<div class="dz-details">
<div class="dz-size"><span data-dz-size></span></div>
<div class="dz-filename"><span data-dz-name></span></div>
</div>
<div class="dz-progress"><span class="dz-upload" data-dz-uploadprogress></span></div>
<div class="dz-error-message"><span data-dz-errormessage></span></div>
<div class="dz-success-mark">
<svg width="54px" height="54px" viewBox="0 0 54 54" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: Sketch 3.2.1 (9971) - http://www.bohemiancoding.com/sketch -->
<title>Check</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<path d="M23.5,31.8431458 L17.5852419,25.9283877 C16.0248253,24.3679711 13.4910294,24.366835 11.9289322,25.9289322 C10.3700136,27.4878508 10.3665912,30.0234455 11.9283877,31.5852419 L20.4147581,40.0716123 C20.5133999,40.1702541 20.6159315,40.2626649 20.7218615,40.3488435 C22.2835669,41.8725651 24.794234,41.8626202 26.3461564,40.3106978 L43.3106978,23.3461564 C44.8771021,21.7797521 44.8758057,19.2483887 43.3137085,17.6862915 C41.7547899,16.1273729 39.2176035,16.1255422 37.6538436,17.6893022 L23.5,31.8431458 Z M27,53 C41.3594035,53 53,41.3594035 53,27 C53,12.6405965 41.3594035,1 27,1 C12.6405965,1 1,12.6405965 1,27 C1,41.3594035 12.6405965,53 27,53 Z" id="Oval-2" stroke-opacity="0.198794158" stroke="#747474" fill-opacity="0.816519475" fill="#FFFFFF" sketch:type="MSShapeGroup"></path>
</g>
</svg>
</div>
<div class="dz-error-mark">
<svg width="54px" height="54px" viewBox="0 0 54 54" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: Sketch 3.2.1 (9971) - http://www.bohemiancoding.com/sketch -->
<title>error</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<g id="Check-+-Oval-2" sketch:type="MSLayerGroup" stroke="#747474" stroke-opacity="0.198794158" fill="#FFFFFF" fill-opacity="0.816519475">
<path d="M32.6568542,29 L38.3106978,23.3461564 C39.8771021,21.7797521 39.8758057,19.2483887 38.3137085,17.6862915 C36.7547899,16.1273729 34.2176035,16.1255422 32.6538436,17.6893022 L27,23.3431458 L21.3461564,17.6893022 C19.7823965,16.1255422 17.2452101,16.1273729 15.6862915,17.6862915 C14.1241943,19.2483887 14.1228979,21.7797521 15.6893022,23.3461564 L21.3431458,29 L15.6893022,34.6538436 C14.1228979,36.2202479 14.1241943,38.7516113 15.6862915,40.3137085 C17.2452101,41.8726271 19.7823965,41.8744578 21.3461564,40.3106978 L27,34.6568542 L32.6538436,40.3106978 C34.2176035,41.8744578 36.7547899,41.8726271 38.3137085,40.3137085 C39.8758057,38.7516113 39.8771021,36.2202479 38.3106978,34.6538436 L32.6568542,29 Z M27,53 C41.3594035,53 53,41.3594035 53,27 C53,12.6405965 41.3594035,1 27,1 C12.6405965,1 1,12.6405965 1,27 C1,41.3594035 12.6405965,53 27,53 Z" id="Oval-2" sketch:type="MSShapeGroup"></path>
</g>
</g>
</svg>
</div>
</div>
</div>
@endsection
فایلی به نام dropzone-config.js در دایرکتوری public/js ایجاد می کنیم که تنظیمات dropezone را در آن قرار می دهیم.
var total_photos_counter = 0;
Dropzone.options.myDropzone = {
uploadMultiple: true,
parallelUploads: 2,
maxFilesize: 16,
previewTemplate: document.querySelector('#preview').innerHTML,
addRemoveLinks: true,
dictRemoveFile: 'Remove file',
dictFileTooBig: 'Image is larger than 16MB',
timeout: 10000,
init: function () {
this.on("removedfile", function (file) {
$.post({
url: '/images-delete',
data: {id: file.name, _token: $('[name="_token"]').val()},
dataType: 'json',
success: function (data) {
total_photos_counter--;
$("#counter").text("# " + total_photos_counter);
}
});
});
},
success: function (file, done) {
total_photos_counter++;
$("#counter").text("# " + total_photos_counter);
}
};
استالهای زیر را در custom.css اضافه می کنیم:
.page-heading {
margin: 20px 0;
color: #666;
-webkit-font-smoothing: antialiased;
font-family: "Segoe UI Light", "Arial", serif;
font-weight: 600;
letter-spacing: 0.05em;
}
#my-dropzone .message {
font-family: "Segoe UI Light", "Arial", serif;
font-weight: 600;
color: #0087F7;
font-size: 1.5em;
letter-spacing: 0.05em;
}
.dropzone {
border: 2px dashed #0087F7;
background: white;
border-radius: 5px;
min-height: 300px;
padding: 90px 0;
vertical-align: baseline;
}
ابتدا دستور زیر را در cmd وارد می کنیم
php artisan make:model Upload -m
سپس فایل create_uploads_table.php در آدرس database/migrations با متد زیر پر می کنیم:
public function up()
{
Schema::create('uploads', function (Blueprint $table) {
$table->increments('id');
$table->text('filename');
$table->text('resized_name');
$table->text('original_name');
$table->timestamps();
});
}
و در آخر برای ایجاد جدول در دیتابیس دستور زیر را در cmd وارد می کنیم.
php artisan migrate
ابتدا کنترل زیر UploadImagesController را با دستور زیر ایجاد می کنیم:
php artisan make:controller UploadImagesController
برای تغییر اندازه تصاویر و ایجاد آیکون، از کتابخانه intervention image استفاده خواهیم کرد. دستور زیر را اجرا کنید تا کتابخانه intervention را از طریق composer آپلود شود:
composer require intervention/image 2.4
شما همچنین خط زیر را در قسمت provides در فایل config/app.php وارد می کنیم:
Intervention\Image\ImageServiceProvider::class,
همچنین در آرایه aliases خط زیر را وارد می کنیم:
'Image' => Intervention\Image\Facades\Image::class,
همچنین در کنترل UploadImagesController دستورات زیر را وارد می کنیم.
<?php
namespace App\Http\Controllers;
use App\Upload;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Response;
use Intervention\Image\Facades\Image;
class UploadImagesController extends Controller
{
private $photos_path;
public function __construct()
{
$this->photos_path = public_path('/images');
}
public function index()
{
$photos = Upload::all();
return view('uploaded-images', compact('photos'));
}
public function create()
{
return view('upload');
}
public function store(Request $request)
{
$photos = $request->file('file');
if (!is_array($photos)) {
$photos = [$photos];
}
if (!is_dir($this->photos_path)) {
mkdir($this->photos_path, 0777);
}
for ($i = 0; $i < count($photos); $i++) {
$photo = $photos[$i];
$name = sha1(date('YmdHis') . str_random(30));
$save_name = $name . '.' . $photo->getClientOriginalExtension();
$resize_name = $name . str_random(2) . '.' . $photo->getClientOriginalExtension();
Image::make($photo)
->resize(250, null, function ($constraints) {
$constraints->aspectRatio();
})
->save($this->photos_path . '/' . $resize_name);
$photo->move($this->photos_path, $save_name);
$upload = new Upload();
$upload->filename = $save_name;
$upload->resized_name = $resize_name;
$upload->original_name = basename($photo->getClientOriginalName());
$upload->save();
}
return Response::json([
'message' => 'Image saved Successfully'
], 200);
}
public function destroy(Request $request)
{
$filename = $request->id;
$uploaded_image = Upload::where('original_name', basename($filename))->first();
if (empty($uploaded_image)) {
return Response::json(['message' => 'Sorry file does not exist'], 400);
}
$file_path = $this->photos_path . '/' . $uploaded_image->filename;
$resized_file = $this->photos_path . '/' . $uploaded_image->resized_name;
if (file_exists($file_path)) {
unlink($file_path);
}
if (file_exists($resized_file)) {
unlink($resized_file);
}
if (!empty($uploaded_image)) {
$uploaded_image->delete();
}
return Response::json(['message' => 'File successfully delete'], 200);
}
}
یک view جدید به نام uploaded-images.blade.php در قسمت view اضافه می کنیم:
@extends('main')
@section('js')
<script src="{{ url('/js/jquery.js') }}"></script>
@endsection
@section('content')
<div class="table-responsive-sm">
<table class="table">
<thead>
<tr>
<th scope="col">Image</th>
<th scope="col">Filename</th>
<th scope="col">Original Filename</th>
<th scope="col">Resized Filename</th>
</tr>
</thead>
<tbody>
@foreach($photos as $photo)
<tr>
<td> image </td>
<td> filename </td>
<td> original_name </td>
<td> resized_name </td>
</tr>
@endforeach
</tbody>
</table>
</div>
@endsection