Browse Source

change file add store

master
Mohammad Khazaee 2 years ago
parent
commit
03055c8d75
  1. 74
      app/Http/Controllers/FileController.php
  2. 16
      app/Http/Middleware/BindCollectionModelMiddleware.php
  3. 2
      app/Http/Resources/CollectionResource.php
  4. 2
      app/Http/Resources/FileResource.php
  5. 38
      app/Jobs/FileConversionQueue.php
  6. 8
      app/Models/Collection.php
  7. 35
      app/Models/File.php
  8. 10
      app/Providers/AppServiceProvider.php
  9. 28
      config/filesystems.php
  10. 2
      database/factories/CollectionFactory.php
  11. 2
      database/factories/FileFactory.php
  12. 2
      database/migrations/2022_07_27_073906_create_collections_table.php
  13. BIN
      public/image-modified.jpeg
  14. BIN
      public/image-modified.png
  15. BIN
      public/image-modified.webp
  16. BIN
      public/image-modified2.jpg
  17. BIN
      public/image.jpg
  18. BIN
      public/imagecircle.png
  19. 67
      resources/views/welcome.blade.php
  20. 6
      routes/api.php

74
app/Http/Controllers/FileController.php

@ -3,18 +3,86 @@
namespace App\Http\Controllers;
use App\Http\Requests\FileStoreRequest;
use App\Http\Resources\FileResource;
use App\Jobs\FileConversionQueue;
use App\Models\File;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
class FileController extends Controller
{
public function show($id)
public function show($collection, $uuid, $ext)
{
//
dump($collection, $uuid, $ext);
}
public function private($collection, $path)
{
Storage::disk(app()->collection->disk)->download($path);
}
public function store(Request $request)
{
// $fileStoreRequest;
// skip policy ---and first level----------
$validated = $request->validate([
"file" => [
"mimes:" . app()->collection->getExts(),
"mimetypes:" . app()->collection->getMimeTypes(),
"dimensions:min_width=" . app()->collection->min_width . ",min_height=" . app()->collection->min_height . ',max_width=' . app()->collection->max_width . ',max_height=' . app()->collection->max_height,
"max:" . app()->collection->max_size,
"min:" . app()->collection->min_size,
],
"alts" => [app()->collection->alt_required ? "required" : "null", 'array'],
"alts.*" => [app()->collection->alt_required ? "required" : "null"],
"description" => [app()->collection->description_required ? "required" : "null"],
]);
DB::beginTransaction();
$urlStorage = '/' . date('y') . '/' . date('m') . app()->getFileUuid;
try {
$file = File::create([
'uuid' => app()->getFileUuid,
'original_name' => $request->name,
'public' => $request->public,
'ext' => $request->file->extension(),
'mimetype' => $request->file->getMimeType(),
'width' => getimagesize($request->file)[0],
'height' => getimagesize($request->file)[1],
'file_size' => $request->file->getSize(),
'sort' => $request->file->getSize(),
'alts' => $request->alts,
'description' => $request->description,
'user_id' => auth()->id(),
'ip' => $request->ip(),
'collection_id' => app()->collection->id,
'published_at' => $request->published_at,
'server_path' => $urlStorage
]);
if (!app()->collection->tmp_support && app()->collection->count == 1) {
File::where('user_id', auth()->id())->delete();
}
$file = $request->file->storeAs($urlStorage, app()->getFileUuid, app()->collection->disk);
if (app()->collection->public) {
Storage::setVisibility($file, 'public');
}
DB::commit();
} catch (\Exception $e) {
DB::rollback();
}
FileConversionQueue::dispatch($file, app()->collection);
return new FileResource($file);
}

16
app/Http/Middleware/BindCollectionModelMiddleware.php

@ -5,6 +5,7 @@ namespace App\Http\Middleware;
use App\Models\Collection;
use Closure;
use Illuminate\Http\Request;
use Illuminate\support\Str;
class BindCollectionModelMiddleware
{
@ -18,9 +19,18 @@ class BindCollectionModelMiddleware
public function handle(Request $request, Closure $next)
{
if ($request->route()->action['as'] == 'api.file.store') {
app()->bind('collection',function() use ($request)
{
return Collection::where('name',$request->route('collections_name'))->get();
app()->bind('collection', function () use ($request) {
return Collection::where('name', $request->route('collections_name'))->get();
});
app()->singleton('getFileUuid', function () {
return Str::uuid();
});
}
if ($request->route()->action['as'] == 'api.file.private') {
app()->bind('collection', function () use ($request) {
return Collection::where('name', $request->route('collections_name'))->get();
});
}

2
app/Http/Resources/CollectionResource.php

@ -33,7 +33,7 @@ class CollectionResource extends JsonResource
"count" => $this->count,
"exts" => $this->exts,
"avalible_exts" => $this->avalible_exts,
"memetypes" => $this->memetypes,
"mimetypes" => $this->mimetypes,
"model" => $this->model,
"expire_date" => $this->expire_date,
"created_at" => $this->created_at,

2
app/Http/Resources/FileResource.php

@ -18,7 +18,7 @@ class FileResource extends JsonResource
"uuid" => $this->uuid,
"original_name" => $this->original_name,
"ext" => $this->ext,
"memetype" => $this->memetype,
"mimetype" => $this->mimetype,
"width" => $this->width,
"height" => $this->height,
"file_size" => $this->file_size,

38
app/Jobs/FileConversionQueue.php

@ -0,0 +1,38 @@
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class FileConversionQueue implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $file = null;
protected $collection = null;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct($file, $collection)
{
$this->file = $file;
$this->collection = $collection;
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
//
}
}

8
app/Models/Collection.php

@ -29,7 +29,7 @@ class Collection extends Model
"description_required",
"exts",
"avalible_exts",
"memetypes",
"mimetypes",
"model",
"expire_date",
];
@ -37,7 +37,7 @@ class Collection extends Model
protected $casts = [
'exts' => 'array',
'avalible_exts' => 'array',
'memetypes' => 'array',
'mimetypes' => 'array',
];
protected function exts(): Attribute
@ -52,15 +52,13 @@ class Collection extends Model
set: fn ($value) => json_encode($value),
);
}
protected function memetypes(): Attribute
protected function mimetypes(): Attribute
{
return Attribute::make(
set: fn ($value) => json_encode($value),
);
}
public function getExts()
{
return implode(",", app()->collection->exts);

35
app/Models/File.php

@ -11,7 +11,7 @@ use Illuminate\Support\Str;
class File extends Model
{
use HasFactory, SoftDeletes, Validatable;
use HasFactory, SoftDeletes;
protected $primaryKey = 'uuid';
@ -19,7 +19,7 @@ class File extends Model
"uuid",
"original_name",
"ext",
"memetype",
"mimetype",
"width",
"server_path",
"height",
@ -37,13 +37,6 @@ class File extends Model
'alts' => 'array',
];
protected function uuid(): Attribute
{
return Attribute::make(
set: fn ($value) => Str::uuid(),
);
}
protected function alts(): Attribute
{
@ -52,16 +45,16 @@ class File extends Model
);
}
public function rules(): array
{
return [
"image" => [
"mimes:" . app()->collection->getExts(),
"mimetypes:" . app()->collection->getMimeTypes(),
"dimensions:min_width=" . app()->collection->min_width . ",min_height=" . app()->collection->min_height . ',max_width=' . app()->collection->max_width . ',max_height='. app()->collection->max_height,
"max:" . app()->collection->max_size,
"min:" . app()->collection->min_size,
],
];
}
// public function rules(): array
// {
// return [
// "image" => [
// "mimes:" . app()->collection->getExts(),
// "mimetypes:" . app()->collection->getMimeTypes(),
// "dimensions:min_width=" . app()->collection->min_width . ",min_height=" . app()->collection->min_height . ',max_width=' . app()->collection->max_width . ',max_height=' . app()->collection->max_height,
// "max:" . app()->collection->max_size,
// "min:" . app()->collection->min_size,
// ],
// ];
// }
}

10
app/Providers/AppServiceProvider.php

@ -2,6 +2,8 @@
namespace App\Providers;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
@ -23,6 +25,12 @@ class AppServiceProvider extends ServiceProvider
*/
public function boot()
{
//
Storage::disk('local')->buildTemporaryUrlsUsing(function ($path, $expiration, $options) {
return URL::temporarySignedRoute(
'api.file.private',
$expiration,
array_merge($options, ['path' => $path])
);
});
}
}

28
config/filesystems.php

@ -33,16 +33,28 @@ return [
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
'url' => env('APP_URL') . '/storage',
'visibility' => 'private',
'throw' => false,
'permissions' => [
'file' => [
'public' => 0644,
'private' => 0600,
],
'dir' => [
'public' => 0755,
'private' => 0700,
],
],
],
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
'throw' => false,
],
// 'public' => [
// 'driver' => 'local',
// 'root' => storage_path('app/public'),
// 'url' => env('APP_URL') . '/storage',
// 'visibility' => 'public',
// 'throw' => false,
// ],
's3' => [
'driver' => 's3',
@ -70,7 +82,7 @@ return [
*/
'links' => [
public_path('storage') => storage_path('app/public'),
// public_path('storage') => storage_path('app/public'),
],
];

2
database/factories/CollectionFactory.php

@ -44,7 +44,7 @@ class CollectionFactory extends Factory
"png",
"webp"
],
"memetypes" => [
"mimetypes" => [
"jpg",
"jpeg",
"png",

2
database/factories/FileFactory.php

@ -21,7 +21,7 @@ class FileFactory extends Factory
"uuid" => 1,
"original_name" => fake()->name(),
"ext" => ['jpg', 'jpeg', 'png', 'webp'][rand(0, 3)],
"memetype" => 'image',
"mimetype" => 'image',
"width" => rand(300, 2000),
"height" => rand(300, 2000),
"file_size" => rand(300, 2000),

2
database/migrations/2022_07_27_073906_create_collections_table.php

@ -34,7 +34,7 @@ return new class extends Migration
$table->json("avalible_exts")->nullable();
$table->json("mimetypes")->nullable();
$table->string("model")->unique()->nullable();
$table->timestamp("expire_date")->nullable();
$table->time("expire_date")->nullable();
$table->timestamps();
$table->softDeletes();
});

BIN
public/image-modified.jpeg

Binary file not shown.

Before

Width: 1000  |  Height: 500  |  Size: 475 KiB

BIN
public/image-modified.png

Binary file not shown.

Before

Width: 500  |  Height: 300  |  Size: 101 KiB

BIN
public/image-modified.webp

Binary file not shown.

BIN
public/image-modified2.jpg

Binary file not shown.

Before

Width: 180  |  Height: 417  |  Size: 20 KiB

BIN
public/image.jpg

Binary file not shown.

Before

Width: 5175  |  Height: 3372  |  Size: 2.6 MiB

BIN
public/imagecircle.png

Binary file not shown.

Before

Width: 180  |  Height: 417  |  Size: 146 KiB

67
resources/views/welcome.blade.php

@ -1,32 +1,41 @@
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Laravel</title>
<!-- Fonts -->
<link href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700&display=swap" rel="stylesheet">
<!-- Styles -->
<style>
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}a{background-color:transparent}[hidden]{display:none}html{font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5}*,:after,:before{box-sizing:border-box;border:0 solid #e2e8f0}a{color:inherit;text-decoration:inherit}svg,video{display:block;vertical-align:middle}video{max-width:100%;height:auto}.bg-white{--bg-opacity:1;background-color:#fff;background-color:rgba(255,255,255,var(--bg-opacity))}.bg-gray-100{--bg-opacity:1;background-color:#f7fafc;background-color:rgba(247,250,252,var(--bg-opacity))}.border-gray-200{--border-opacity:1;border-color:#edf2f7;border-color:rgba(237,242,247,var(--border-opacity))}.border-t{border-top-width:1px}.flex{display:flex}.grid{display:grid}.hidden{display:none}.items-center{align-items:center}.justify-center{justify-content:center}.font-semibold{font-weight:600}.h-5{height:1.25rem}.h-8{height:2rem}.h-16{height:4rem}.text-sm{font-size:.875rem}.text-lg{font-size:1.125rem}.leading-7{line-height:1.75rem}.mx-auto{margin-left:auto;margin-right:auto}.ml-1{margin-left:.25rem}.mt-2{margin-top:.5rem}.mr-2{margin-right:.5rem}.ml-2{margin-left:.5rem}.mt-4{margin-top:1rem}.ml-4{margin-left:1rem}.mt-8{margin-top:2rem}.ml-12{margin-left:3rem}.-mt-px{margin-top:-1px}.max-w-6xl{max-width:72rem}.min-h-screen{min-height:100vh}.overflow-hidden{overflow:hidden}.p-6{padding:1.5rem}.py-4{padding-top:1rem;padding-bottom:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.pt-8{padding-top:2rem}.fixed{position:fixed}.relative{position:relative}.top-0{top:0}.right-0{right:0}.shadow{box-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px 0 rgba(0,0,0,.06)}.text-center{text-align:center}.text-gray-200{--text-opacity:1;color:#edf2f7;color:rgba(237,242,247,var(--text-opacity))}.text-gray-300{--text-opacity:1;color:#e2e8f0;color:rgba(226,232,240,var(--text-opacity))}.text-gray-400{--text-opacity:1;color:#cbd5e0;color:rgba(203,213,224,var(--text-opacity))}.text-gray-500{--text-opacity:1;color:#a0aec0;color:rgba(160,174,192,var(--text-opacity))}.text-gray-600{--text-opacity:1;color:#718096;color:rgba(113,128,150,var(--text-opacity))}.text-gray-700{--text-opacity:1;color:#4a5568;color:rgba(74,85,104,var(--text-opacity))}.text-gray-900{--text-opacity:1;color:#1a202c;color:rgba(26,32,44,var(--text-opacity))}.underline{text-decoration:underline}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.w-5{width:1.25rem}.w-8{width:2rem}.w-auto{width:auto}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}@media (min-width:640px){.sm\:rounded-lg{border-radius:.5rem}.sm\:block{display:block}.sm\:items-center{align-items:center}.sm\:justify-start{justify-content:flex-start}.sm\:justify-between{justify-content:space-between}.sm\:h-20{height:5rem}.sm\:ml-0{margin-left:0}.sm\:px-6{padding-left:1.5rem;padding-right:1.5rem}.sm\:pt-0{padding-top:0}.sm\:text-left{text-align:left}.sm\:text-right{text-align:right}}@media (min-width:768px){.md\:border-t-0{border-top-width:0}.md\:border-l{border-left-width:1px}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (min-width:1024px){.lg\:px-8{padding-left:2rem;padding-right:2rem}}@media (prefers-color-scheme:dark){.dark\:bg-gray-800{--bg-opacity:1;background-color:#2d3748;background-color:rgba(45,55,72,var(--bg-opacity))}.dark\:bg-gray-900{--bg-opacity:1;background-color:#1a202c;background-color:rgba(26,32,44,var(--bg-opacity))}.dark\:border-gray-700{--border-opacity:1;border-color:#4a5568;border-color:rgba(74,85,104,var(--border-opacity))}.dark\:text-white{--text-opacity:1;color:#fff;color:rgba(255,255,255,var(--text-opacity))}.dark\:text-gray-400{--text-opacity:1;color:#cbd5e0;color:rgba(203,213,224,var(--text-opacity))}.dark\:text-gray-500{--tw-text-opacity:1;color:#6b7280;color:rgba(107,114,128,var(--tw-text-opacity))}}
</style>
<style>
body {
font-family: 'Nunito', sans-serif;
}
</style>
</head>
<body class="antialiased">
<form action="/upload" method="post" enctype="multipart/form-data">
@csrf
<input type="file" name="image">
<br>
<input type="submit" value="s">
</form>
</body>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Laravel</title>
<!-- Fonts -->
<link href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700&display=swap" rel="stylesheet">
<!-- Styles -->
</head>
<body class="antialiased">
<form action="/upload" method="post" enctype="multipart/form-data">
@csrf
<input type="file" name="file">
<br>
<input type="text" name="" placeholder=""><br>
<input type="text" name="" placeholder="ttt"><br>
<input type="text" name="" placeholder="ttt"><br>
<input type="text" name="" placeholder="ttt"><br>
<input type="text" name="" placeholder="ttt"><br>
<input type="text" name="" placeholder="ttt"><br>
<input type="text" name="" placeholder="ttt"><br>
<input type="text" name="" placeholder="ttt"><br>
<input type="text" name="" placeholder="ttt"><br>
<input type="text" name="" placeholder="ttt"><br>
<input type="text" name="" placeholder="ttt"><br>
<input type="submit" value="s">
</form>
</body>
</html>

6
routes/api.php

@ -21,6 +21,8 @@ use Illuminate\Support\Facades\Route;
Route::group(['as' => 'api.'], function () {
Route::apiResource('collections', CollectionController::class);
Route::delete('/collections/{collection}', [CollectionController::class, "destroy"])->withTrashed();
Route::post('{collection_name}/{model_name?}', [FileController::class, 'store'])->name('file.store');
Route::delete('collections/{collection}', [CollectionController::class, "destroy"])->withTrashed();
Route::get('{collection_name}/{uuid}.{extention}', [FileController::class, 'show'])->name('file.show');
Route::get('{collection_name}/{path}', [FileController::class, 'private'])->name('file.private');
Route::post('{collection_name}', [FileController::class, 'store'])->name('file.store');
});
Loading…
Cancel
Save