This commit is contained in:
2026-04-15 19:34:56 +05:00
parent 34ffed1e4a
commit e243821f50
26 changed files with 2072 additions and 1258 deletions

View File

@@ -28,37 +28,61 @@ class ImageResize
* @param $path * @param $path
* @param $size * @param $size
* @param $type * @param $type
* @param bool $deleteOriginal
* @return string * @return string
* @throws \Exception
*/ */
public function resize($path, $size, $type) public function resize($path, $size, $type, $deleteOriginal = false)
{ {
// 1. Resolve source path
$srcPath = file_exists(public_path($path))
? public_path($path)
: storage_path('app/public/' . $path);
if (!file_exists($srcPath)) {
if (file_exists($path)) {
$srcPath = $path;
} else {
// Last ditch effort: try to get from S3 if it's not local
if (env('FILESYSTEM_DISK') == 's3' && Storage::disk('s3')->exists($path)) {
$fileContent = Storage::disk('s3')->get($path);
$tmpLocal = storage_path('app/public/temp_' . basename($path));
file_put_contents($tmpLocal, $fileContent);
$srcPath = $tmpLocal;
$deleteOriginal = true; // Clean up the temp download
} else {
throw new \Exception("Source image not found: " . $path);
}
}
}
// 2. Prepare thumb destination
$name = basename($path); $name = basename($path);
$folder = $this->mkdir($type); $folder = $this->mkdir($type);
$path_thumb = "{$folder}/{$name}"; $path_thumb = "{$folder}/{$name}";
$absPathThumb = public_path($path_thumb);
// 3. Resize and Save Thumb
$img = Imagee::make($srcPath);
$img->resize($size, null, function ($constraint) {
$constraint->aspectRatio();
});
$img->save($absPathThumb, 100);
// 4. Handle S3 Upload
if (env('FILESYSTEM_DISK') == 's3') { if (env('FILESYSTEM_DISK') == 's3') {
try{ Storage::disk('s3')->put($path_thumb, file_get_contents($absPathThumb));
$file = Storage::disk("public")->get($path); // Remove local thumb after S3 upload
}catch(Exception $e){ if (file_exists($absPathThumb)) {
$file = file_get_contents($path); unlink($absPathThumb);
} }
$img = Imagee::make($file);
$img->resize($size, null, function ($constraint) {
$constraint->aspectRatio();
});
// delete temp file
$img->save("{$path_thumb}", 100);
Storage::disk('s3')->put($path_thumb, file_get_contents($path_thumb));
} else {
// source can be in storage/app/public (from ->store('temp','public')) or public/
$srcPath = file_exists(public_path($path))
? public_path($path)
: storage_path('app/public/' . $path);
$img = Imagee::make($srcPath);
$img->resize($size, null, function ($constraint) {
$constraint->aspectRatio();
});
$img->save(public_path($path_thumb), 100);
} }
// 5. Cleanup original if requested
if ($deleteOriginal && file_exists($srcPath)) {
unlink($srcPath);
}
return $path_thumb; return $path_thumb;
} }
} }

View File

@@ -130,23 +130,9 @@ class Controller extends ExController
private function storeImageToS3($image): string private function storeImageToS3($image): string
{ {
$path = '';
// first store temp file and resize it, then upload to s3
// 1 - store temp file
$tempPath = $image->store('temp', 'public'); $tempPath = $image->store('temp', 'public');
if ($tempPath) {
$tempFilePath = storage_path('app/public/' . $tempPath); $resizer = new ImageResize();
$image = new ImageResize(); return $resizer->resize($tempPath, 322, 'brands', true);
$path = $image->resize($tempPath, 322, 'brands');
// 2 - upload to s3 or keep local
if (in_array(env('FILESYSTEM_DISK'), ['s3', 'minio'])) {
Storage::disk('s3')->put($path, file_get_contents($path));
unlink($path);
}
}
return $path;
} }
} }

View File

@@ -101,31 +101,11 @@ class Store extends FormRequest
*/ */
public function getPosterThumb() public function getPosterThumb()
{ {
$url = $this->storeImageToS3($this->file('poster')); $image = $this->file('poster');
return $url;
}
private function storeImageToS3($image): string
{
$path = '';
// first store temp file and resize it, then upload to s3
// 1 - store temp file
$tempPath = $image->store('temp', 'public'); $tempPath = $image->store('temp', 'public');
if ($tempPath) {
// $tempFilePath = storage_path('app/public/' . $tempPath); $resizer = new ImageResize();
$image = new ImageResize(); return $resizer->resize($tempPath, 322, 'posters', true);
$path = $image->resize($tempPath, 322, 'posters');
// 2 - upload to s3 or keep local
if (in_array(env('FILESYSTEM_DISK'), ['s3', 'minio'])) {
Storage::disk('s3')->put($path, file_get_contents($path));
unlink($path);
}
}
return $path;
} }
/** /**

View File

@@ -123,40 +123,21 @@ class Update extends FormRequest
// delete old file from s3 // delete old file from s3
Storage::disk('s3')->delete($product->poster_thumb); Storage::disk('s3')->delete($product->poster_thumb);
} else { } else {
// delete old file // delete old file local
unlink($product->poster_thumb); $oldPath = public_path($product->poster_thumb);
if (is_file($oldPath)) unlink($oldPath);
} }
$url = $this->storeImageToS3($this->file('poster')); $image = $this->file('poster');
return $url; $tempPath = $image->store('temp', 'public');
$resizer = new ImageResize();
return $resizer->resize($tempPath, 322, 'posters', true);
} }
return $product->poster_thumb; return $product->poster_thumb;
} }
private function storeImageToS3($image): string
{
$path = '';
// first store temp file and resize it, then upload to s3
// 1 - store temp file
$tempPath = $image->store('temp', 'public');
if ($tempPath) {
//$tempFilePath = storage_path('app/public/' . $tempPath);
$image = new ImageResize();
$path = $image->resize($tempPath, 322, 'posters');
// 2 - upload to s3 or keep local
if (in_array(env('FILESYSTEM_DISK'), ['s3', 'minio'])) {
Storage::disk('s3')->put($path, file_get_contents($path));
unlink($path);
}
}
return $path;
}
/** /**
* @return array * @return array
*/ */

View File

@@ -53,9 +53,19 @@ class Child
foreach ($color['screens'] as $screen) { foreach ($color['screens'] as $screen) {
$folder = Carbon::now()->format('Y/m/d'); $folder = Carbon::now()->format('Y/m/d');
$path = $screen['image']->store($screen['image']); // Store original
$path = $screen['image']->store("uploads/screens/{$folder}");
$thumbPath = $this->storeImageToS3($screen['image']); // Store and resize thumb
$tempPath = $screen['image']->store('temp', 'public');
$thumbPath = $this->image->resize($tempPath, 322, 'screens', true);
// Get screen size (local or s3)
if (env('FILESYSTEM_DISK') == 's3') {
$this->size = Storage::disk('s3')->size($path);
} else {
$this->size = filesize(public_path($path));
}
Screen::create([ Screen::create([
'path' => $path, 'path' => $path,
@@ -68,28 +78,4 @@ class Child
} }
} }
} }
private function storeImageToS3($image): string
{
$path = '';
// first store temp file and resize it, then upload to s3
// 1 - store temp file
$tempPath = $image->store('temp', 'public');
if ($tempPath) {
$tempFilePath = storage_path('app/public/' . $tempPath);
$image = new ImageResize();
$path = $image->resize($tempPath, 322, 'screens');
$this->size = filesize(public_path($path));
// 2 - upload local $path to s3
// Store the image on S3
if (in_array(env('FILESYSTEM_DISK'), ['s3', 'minio'])) {
Storage::disk('s3')->put($path, file_get_contents(public_path($path)));
unlink($path);
}
}
return $path;
}
} }

View File

@@ -79,19 +79,23 @@ class ChildUpdate
{ {
if (!empty($screens)) { if (!empty($screens)) {
foreach ($screens as $screen) { foreach ($screens as $screen) {
if ($screen['id'] == 'undefined' || $screen['id'] == 'null' || $screen['id'] = null) { if ($screen['id'] == 'undefined' || $screen['id'] == 'null' || $screen['id'] == null) {
$folder = Carbon::now()->format('Y/m/d'); $folder = Carbon::now()->format('Y/m/d');
if ($screen['image']) { if ($screen['image']) {
// 1. Store original (S3 if enabled)
$path = $screen['image']->store("uploads/screens/{$folder}"); $path = $screen['image']->store("uploads/screens/{$folder}");
$image = Screen::create([
// 2. Local temp for resizing
$tempPath = $screen['image']->store('temp', 'public');
$thumbPath = $this->image->resize($tempPath, 322, 'screens', true);
Screen::create([
'path' => $path, 'path' => $path,
'path_thumb' => "uploads/screens/thumbs/{$folder}/" . basename($path), 'path_thumb' => $thumbPath,
'name' => basename($path), 'name' => basename($path),
'product_id' => $child_id, 'product_id' => $child_id,
'size' => Storage::size($path) 'size' => Storage::disk(env('FILESYSTEM_DISK'))->size($path)
]); ]);
$this->image->resize($image->path, 322, 'screens');
} }
} }
} }

View File

@@ -33,18 +33,21 @@ class Screen
*/ */
public function handle() public function handle()
{ {
$folder = Carbon::now()->format('Y/m/d');
//$folder = 'uploads/screens/'.date('Y', time()).'/'.Carbon::now()->format('m').'/'.Carbon::now()->format('d');
foreach ($this->request as $screen) { foreach ($this->request as $screen) {
$folder = Carbon::now()->format('Y/m/d');
// 1. Store original (S3 if enabled)
$path = $screen->store("uploads/screens/original/{$folder}"); $path = $screen->store("uploads/screens/original/{$folder}");
$thumb = $this->img->resize($path, 350, 'screens');
// 2. Local temp for resizing
$tempPath = $screen->store('temp', 'public');
$thumb = $this->img->resize($tempPath, 350, 'screens', true);
$screens = new Screens(); $screens = new Screens();
$screens->name = basename($path); $screens->name = basename($path);
$screens->path = $path; $screens->path = $path;
$screens->path_thumb = $thumb; $screens->path_thumb = $thumb;
$screens->size = filesize($path); $screens->size = Storage::disk(env('FILESYSTEM_DISK'))->size($path);
$screens->product_id = $this->id; $screens->product_id = $this->id;
$screens->save(); $screens->save();
} }

View File

@@ -147,10 +147,10 @@ class Category extends Model
); );
} }
return (string) $this->image; return env('APP_URL') . '/' . $this->image;
} }
return (string) 'images/nophoto.jpg'; return env('APP_URL') . '/images/nophoto.jpg';
} }
public function getParentId(): int public function getParentId(): int

View File

@@ -26,7 +26,7 @@ class AppServiceProvider extends ServiceProvider
date_default_timezone_set('Asia/Tashkent'); date_default_timezone_set('Asia/Tashkent');
// set lang to uz // set lang to uz
if (App::environment(['staging', 'production'])) { if (App::environment(['staging', 'production'])) {
URL::forceScheme('https'); URL::forceScheme('http');
} }
} }
} }

View File

@@ -92,6 +92,20 @@ services:
- internal - internal
ports: ports:
- "8080:8080" - "8080:8080"
minio:
image: 'minio/minio:latest'
container_name: quyoshli-minio
ports:
- '9100:9100'
- '9101:9101'
environment:
MINIO_ROOT_USER: 'admin'
MINIO_ROOT_PASSWORD: 'password'
volumes:
- 'quyoshli-minio:/data'
command: server /data --address ":9100" --console-address ":9101"
networks:
- internal
volumes: volumes:
quyoshli-postgres: quyoshli-postgres:
driver: local driver: local
@@ -99,3 +113,5 @@ volumes:
driver: local driver: local
quyoshli-redis: quyoshli-redis:
driver: local driver: local
quyoshli-minio:
driver: local

2959
package-lock.json generated Executable file → Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

View File

@@ -318,7 +318,7 @@
<div class="text-center"> <div class="text-center">
<img <img
id="uploadPreview" id="uploadPreview"
:src="product.poster" :src="getPosterPreview()"
style=" style="
width: 300px; width: 300px;
height: auto; height: auto;
@@ -1110,6 +1110,12 @@ export default {
this.remaincharUZCount(); this.remaincharUZCount();
this.setCategory(); this.setCategory();
this.products.childrens.forEach((child) => {
if (!child.filesDataForUpload) {
this.$set(child, "filesDataForUpload", []);
}
});
if (this.products.categories.length == 0) { if (this.products.categories.length == 0) {
this.watch_count = { this.watch_count = {
first: 2, first: 2,
@@ -1120,6 +1126,12 @@ export default {
}, },
methods: { methods: {
getPosterPreview() {
if (this.products.poster instanceof File) {
return URL.createObjectURL(this.products.poster);
}
return this.products.poster;
},
setCategory() { setCategory() {
if (this.products.categories[0]) { if (this.products.categories[0]) {
if (this.products.categories[0].parent) { if (this.products.categories[0].parent) {
@@ -1332,10 +1344,25 @@ export default {
); );
} }
formData.append( if (this.products.childrens[i].screens[screens].file) {
"colors[" + i + "][screens][" + screens + "][image]", formData.append(
this.products.childrens[i].screens[screens].file "colors[" + i + "][screens][" + screens + "][image]",
); this.products.childrens[i].screens[screens].file
);
}
}
if (this.products.childrens[i].filesDataForUpload) {
for (
let f = 0;
f < this.products.childrens[i].filesDataForUpload.length;
f++
) {
formData.append(
"colors[" + i + "][screens][new_" + f + "][image]",
this.products.childrens[i].filesDataForUpload[f].file
);
}
} }
} }
@@ -1410,6 +1437,7 @@ export default {
sizes: [], sizes: [],
article_number: null, article_number: null,
screens: [], screens: [],
filesDataForUpload: [],
}); });
}, },

View File

@@ -335,6 +335,7 @@
<div class="text-center"> <div class="text-center">
<img <img
id="uploadPreview" id="uploadPreview"
:src="getPosterPreview()"
style=" style="
width: 300px; width: 300px;
height: auto; height: auto;
@@ -1172,6 +1173,12 @@ export default {
}, },
methods: { methods: {
getPosterPreview() {
if (this.product.poster instanceof File) {
return URL.createObjectURL(this.product.poster);
}
return this.product.poster;
},
async StoreProduct() { async StoreProduct() {
const header = { const header = {
headers: { headers: {
@@ -1263,10 +1270,25 @@ export default {
screens < this.product.colors[i].screens.length; screens < this.product.colors[i].screens.length;
screens++ screens++
) { ) {
formData.append( if (this.product.colors[i].screens[screens].file) {
"colors[" + i + "][screens][" + screens + "][image]", formData.append(
this.product.colors[i].screens[screens].file "colors[" + i + "][screens][" + screens + "][image]",
); this.product.colors[i].screens[screens].file
);
}
}
if (this.product.colors[i].filesDataForUpload) {
for (
let f = 0;
f < this.product.colors[i].filesDataForUpload.length;
f++
) {
formData.append(
"colors[" + i + "][screens][new_" + f + "][image]",
this.product.colors[i].filesDataForUpload[f].file
);
}
} }
} }

View File

@@ -33,10 +33,10 @@
@endsection @endsection
@push('css') @push('css')
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/vue-file-agent@latest/dist/vue-file-agent.css" />
@endpush @endpush
@push('js') @push('js')
{{-- @vite('resources/js/app.js')</script> --}}
@vite('resources/js/app.js') @vite('resources/js/app.js')
<script> <script>
@@ -57,18 +57,4 @@
}); });
}); });
</script> </script>
<script type="text/javascript">
function PreviewImage() {
var oFReader = new FileReader();
oFReader.readAsDataURL(document.getElementById("uploadImage").files[0]);
oFReader.onload = function(oFREvent) {
document.getElementById("uploadPreview").src = oFREvent.target.result;
};
};
</script>
@vite('resources/js/app.js')
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/vue-file-agent@latest/dist/vue-file-agent.css" />
@endpush @endpush

View File

@@ -39,7 +39,7 @@
@endpush @endpush
@push('js') @push('js')
@vite('resources/js/app.js')</script> @vite('resources/js/app.js')
<script> <script>
$(document).ready(function() { $(document).ready(function() {
@@ -59,15 +59,4 @@
}); });
}); });
</script> </script>
<script type="text/javascript">
function PreviewImage() {
var oFReader = new FileReader();
oFReader.readAsDataURL(document.getElementById("uploadImage").files[0]);
oFReader.onload = function(oFREvent) {
document.getElementById("uploadPreview").src = oFREvent.target.result;
};
};
</script>
@endpush @endpush

View File

@@ -1,4 +1,4 @@
@extends('site.layouts.app') @extends('layouts.app')
@section('title', trans('app.main')) @section('title', trans('app.main'))

30
scratch/create_bucket.php Normal file
View File

@@ -0,0 +1,30 @@
<?php
require 'vendor/autoload.php';
use Aws\S3\S3Client;
use Aws\Exception\AwsException;
$s3Client = new S3Client([
'version' => 'latest',
'region' => 'us-east-1',
'endpoint' => 'http://minio:9000',
'use_path_style_endpoint' => true,
'credentials' => [
'key' => 'admin',
'secret' => 'password',
],
]);
try {
$result = $s3Client->createBucket([
'Bucket' => 'quyoshli',
]);
echo "Bucket 'quyoshli' created successfully.\n";
} catch (AwsException $e) {
if ($e->getAwsErrorCode() == 'BucketAlreadyOwnedByYou' || $e->getAwsErrorCode() == 'BucketAlreadyExists') {
echo "Bucket 'quyoshli' already exists.\n";
} else {
echo $e->getMessage() . "\n";
}
}