fix upload using file upload storage php not base64

This commit is contained in:
2025-07-11 14:21:37 +07:00
parent e52c4d1d27
commit 748ac8a77e
4 changed files with 306 additions and 73 deletions

View File

@@ -6,6 +6,8 @@ use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\Precheck;
use App\Models\Transaction;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Log;
class PrechecksController extends Controller
{
@@ -32,41 +34,152 @@ class PrechecksController extends Controller
'pressure_high' => 'required|numeric|min:0',
'pressure_low' => 'nullable|numeric|min:0',
'cabin_temperature' => 'nullable|numeric',
'cabin_temperature_image' => 'nullable|string',
'cabin_temperature_image' => 'nullable|image|mimes:jpeg,png,jpg|max:2048',
'ac_condition' => 'nullable|in:' . implode(',', Precheck::getAcConditionOptions()),
'ac_image' => 'nullable|string',
'ac_image' => 'nullable|image|mimes:jpeg,png,jpg|max:2048',
'blower_condition' => 'nullable|in:' . implode(',', Precheck::getBlowerConditionOptions()),
'blower_image' => 'nullable|string',
'blower_image' => 'nullable|image|mimes:jpeg,png,jpg|max:2048',
'evaporator_condition' => 'nullable|in:' . implode(',', Precheck::getEvaporatorConditionOptions()),
'evaporator_image' => 'nullable|string',
'evaporator_image' => 'nullable|image|mimes:jpeg,png,jpg|max:2048',
'compressor_condition' => 'nullable|in:' . implode(',', Precheck::getCompressorConditionOptions()),
'precheck_notes' => 'nullable|string',
'front_image' => 'required|string',
'front_image' => 'required|image|mimes:jpeg,png,jpg|max:2048',
]);
// Pastikan transaction_id sama dengan $transaction->id
$precheck = Precheck::create([
$data = [
'transaction_id' => $transaction->id,
'precheck_by' => auth()->id(),
'precheck_at' => now(),
'police_number' => $transaction->police_number,
'spk_number' => $transaction->spk,
'front_image' => $request->front_image,
'kilometer' => $request->kilometer,
'pressure_high' => $request->pressure_high,
'pressure_low' => $request->pressure_low,
'cabin_temperature' => $request->cabin_temperature,
'cabin_temperature_image' => $request->cabin_temperature_image,
'ac_condition' => $request->ac_condition,
'ac_image' => $request->ac_image,
'blower_condition' => $request->blower_condition,
'blower_image' => $request->blower_image,
'evaporator_condition' => $request->evaporator_condition,
'evaporator_image' => $request->evaporator_image,
'compressor_condition' => $request->compressor_condition,
'precheck_notes' => $request->precheck_notes,
]);
];
return redirect()->route('transaction')->with('success', 'Precheck berhasil disimpan');
// Handle file uploads
$imageFields = [
'front_image', 'cabin_temperature_image', 'ac_image',
'blower_image', 'evaporator_image'
];
foreach ($imageFields as $field) {
if ($request->hasFile($field) && $request->file($field)->isValid()) {
try {
$file = $request->file($field);
// Generate unique filename
$filename = time() . '_' . uniqid() . '_' . $field . '.' . $file->getClientOriginalExtension();
// Create directory path
$directory = 'prechecks/' . date('Y/m');
// Ensure base storage directory exists
$this->ensureStorageDirectoryExists();
// Ensure prechecks directory exists
if (!Storage::disk('public')->exists('prechecks')) {
Storage::disk('public')->makeDirectory('prechecks', 0755, true);
Log::info('Created prechecks directory');
}
// Ensure year directory exists
$yearDir = 'prechecks/' . date('Y');
if (!Storage::disk('public')->exists($yearDir)) {
Storage::disk('public')->makeDirectory($yearDir, 0755, true);
Log::info('Created year directory: ' . $yearDir);
}
// Ensure month directory exists
if (!Storage::disk('public')->exists($directory)) {
Storage::disk('public')->makeDirectory($directory, 0755, true);
Log::info('Created month directory: ' . $directory);
}
// Store file in organized directory structure
$path = $file->storeAs($directory, $filename, 'public');
// Store file path
$data[$field] = $path;
// Store metadata
$data[$field . '_metadata'] = [
'original_name' => $file->getClientOriginalName(),
'size' => $file->getSize(),
'mime_type' => $file->getMimeType(),
'uploaded_at' => now()->toISOString(),
];
Log::info('File uploaded successfully: ' . $path);
} catch (\Exception $e) {
// Log error for debugging
Log::error('File upload failed: ' . $e->getMessage(), [
'field' => $field,
'file' => $file->getClientOriginalName(),
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString()
]);
return back()->withErrors(['error' => 'Gagal mengupload file: ' . $field . '. Error: ' . $e->getMessage()]);
}
}
}
try {
Precheck::create($data);
return redirect()->route('transaction')->with('success', 'Precheck berhasil disimpan');
} catch (\Exception $e) {
Log::error('Precheck creation failed: ' . $e->getMessage());
return back()->withErrors(['error' => 'Gagal menyimpan data precheck. Silakan coba lagi.']);
}
}
/**
* Ensure the base storage directory exists
*/
private function ensureStorageDirectoryExists()
{
$storagePath = storage_path('app/public');
if (!is_dir($storagePath)) {
if (!mkdir($storagePath, 0755, true)) {
Log::error('Failed to create storage directory: ' . $storagePath);
throw new \Exception('Cannot create storage directory: ' . $storagePath . '. Please run: php fix_permissions.php or manually create the directory.');
}
Log::info('Created storage directory: ' . $storagePath);
}
// Check if directory is writable
if (!is_writable($storagePath)) {
Log::error('Storage directory is not writable: ' . $storagePath);
throw new \Exception(
'Storage directory is not writable: ' . $storagePath . '. ' .
'Please run one of these commands from your project root: ' .
'1) php fix_permissions.php ' .
'2) chmod -R 775 storage/ ' .
'3) mkdir -p storage/app/public/prechecks/' . date('Y/m')
);
}
// Check if we can create subdirectories
$testDir = $storagePath . '/test_' . time();
if (!mkdir($testDir, 0755, true)) {
Log::error('Cannot create subdirectories in storage: ' . $storagePath);
throw new \Exception(
'Cannot create subdirectories in storage. ' .
'Please check permissions and run: php fix_permissions.php'
);
}
// Clean up test directory
rmdir($testDir);
Log::info('Storage directory is properly configured: ' . $storagePath);
}
}

View File

@@ -4,6 +4,7 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Storage;
class Precheck extends Model
{
@@ -16,17 +17,22 @@ class Precheck extends Model
'police_number',
'spk_number',
'front_image',
'front_image_metadata',
'kilometer',
'pressure_high',
'pressure_low',
'cabin_temperature',
'cabin_temperature_image',
'cabin_temperature_image_metadata',
'ac_condition',
'ac_image',
'ac_image_metadata',
'blower_condition',
'blower_image',
'blower_image_metadata',
'evaporator_condition',
'evaporator_image',
'evaporator_image_metadata',
'compressor_condition',
'precheck_notes'
];
@@ -37,6 +43,11 @@ class Precheck extends Model
'pressure_high' => 'decimal:2',
'pressure_low' => 'decimal:2',
'cabin_temperature' => 'decimal:2',
'front_image_metadata' => 'array',
'cabin_temperature_image_metadata' => 'array',
'ac_image_metadata' => 'array',
'blower_image_metadata' => 'array',
'evaporator_image_metadata' => 'array',
];
/**
@@ -59,6 +70,67 @@ class Precheck extends Model
return $this->belongsTo(User::class, 'precheck_by');
}
/**
* Get front image URL
*/
public function getFrontImageUrlAttribute()
{
return $this->front_image ? Storage::disk('public')->url($this->front_image) : null;
}
/**
* Get cabin temperature image URL
*/
public function getCabinTemperatureImageUrlAttribute()
{
return $this->cabin_temperature_image ? Storage::disk('public')->url($this->cabin_temperature_image) : null;
}
/**
* Get AC image URL
*/
public function getAcImageUrlAttribute()
{
return $this->ac_image ? Storage::disk('public')->url($this->ac_image) : null;
}
/**
* Get blower image URL
*/
public function getBlowerImageUrlAttribute()
{
return $this->blower_image ? Storage::disk('public')->url($this->blower_image) : null;
}
/**
* Get evaporator image URL
*/
public function getEvaporatorImageUrlAttribute()
{
return $this->evaporator_image ? Storage::disk('public')->url($this->evaporator_image) : null;
}
/**
* Delete associated files when model is deleted
*/
protected static function boot()
{
parent::boot();
static::deleting(function ($precheck) {
$imageFields = [
'front_image', 'cabin_temperature_image', 'ac_image',
'blower_image', 'evaporator_image'
];
foreach ($imageFields as $field) {
if ($precheck->$field && Storage::disk('public')->exists($precheck->$field)) {
Storage::disk('public')->delete($precheck->$field);
}
}
});
}
/**
* Get the AC condition options
*