mirror of
https://github.com/10h30/laravel-file-upload-series.git
synced 2026-07-11 18:55:57 +09:00
Complete Part 4
This commit is contained in:
@@ -4,11 +4,12 @@
|
||||
|
||||
👉 Code cho từng phần nằm ở **các branch riêng**:
|
||||
|
||||
| Phần | Tiêu đề | Branch |
|
||||
| ---- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
|
||||
| 1 | File Upload cơ bản trong Laravel | [`part-1-basic-upload`](https://github.com/10h30/laravel-file-upload-series/tree/part-1-basic-upload) |
|
||||
| 2 | Validation & Bảo mật khi upload | [`part-2-validation-security`](https://github.com/10h30/laravel-file-upload-series/tree/part-2-validation-security) |
|
||||
| 3 | Upload cùng lúc nhiều file | [`part-3-multiple-file-upload`](https://github.com/10h30/laravel-file-upload-series/tree/part-3-multiple-file-upload) |
|
||||
| Phần | Tiêu đề | Branch |
|
||||
| ---- | ------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
|
||||
| 1 | File Upload cơ bản trong Laravel | [`part-1-basic-upload`](https://github.com/10h30/laravel-file-upload-series/tree/part-1-basic-upload) |
|
||||
| 2 | Validation & Bảo mật khi upload | [`part-2-validation-security`](https://github.com/10h30/laravel-file-upload-series/tree/part-2-validation-security) |
|
||||
| 3 | Upload cùng lúc nhiều file | [`part-3-multiple-file-upload`](https://github.com/10h30/laravel-file-upload-series/tree/part-3-multiple-file-upload) |
|
||||
| 4 | Hiển thị và xoá các file đã upload | [`part-4-manage-uploads`](https://github.com/10h30/laravel-file-upload-series/tree/part-4-manage-uploads) |
|
||||
| |
|
||||
|
||||
> 📖 Mỗi branch tương ứng với một phần trong series blog. Bạn có thể clone và chạy từng phần riêng biệt để dễ theo dõi.
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\Upload;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
@@ -14,7 +15,8 @@ class UploadController extends Controller
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return view('upload');
|
||||
$uploads = Upload::latest()->get();
|
||||
return view('upload', compact('uploads'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -65,8 +67,14 @@ class UploadController extends Controller
|
||||
// Lưu file bằng storeAs với tên file mới
|
||||
$storedFilePath = $file->storeAs($directory, $finalFilename, $disk); // Trả về đường dẫn tương đối: 'uploads/ten_file_cuoi_cung.jpg'
|
||||
$storedFilePaths[] = $storedFilePath; // Thêm đường dẫn file đã lưu vào array $storedFilePaths
|
||||
}
|
||||
|
||||
// Tạo bản ghi mới trong table uploads của database
|
||||
Upload::create([
|
||||
'filename' => $storedFilePath,
|
||||
'original_filename' => $originalFilename,
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
// Chuyển hướng về trang trước đó
|
||||
return back()->with('success', 'You have successfully uploaded ' . $numberOfFiles . ' files')
|
||||
@@ -75,4 +83,16 @@ class UploadController extends Controller
|
||||
// Gửi kèm array các tên file gốc vào session flash data với key 'original_filenames'
|
||||
->with('original_filenames', $originalFilenames);
|
||||
}
|
||||
|
||||
public function destroy(Upload $upload)
|
||||
{
|
||||
// Xoá file vật lý khỏi disk 'public' dựa vào đường dẫn lưu trong $upload->filename
|
||||
Storage::disk('public')->delete($upload->filename);
|
||||
|
||||
// Xoá bản ghi tương ứng trong database
|
||||
$upload->delete();
|
||||
|
||||
// Chuyển hướng người dùng về trang trước đó với thông báo thành công
|
||||
return back()->with('success', 'You have successfully deleted ' . $upload->original_filename);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Upload extends Model
|
||||
{
|
||||
protected $fillable = [
|
||||
'filename',
|
||||
'original_filename'
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('uploads', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('filename');
|
||||
$table->string('original_filename');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('uploads');
|
||||
}
|
||||
};
|
||||
@@ -47,7 +47,7 @@
|
||||
@if (session("stored_paths") && is_array(session("stored_paths")))
|
||||
<div class="mt-4">
|
||||
<p>Uploaded Files:</p>
|
||||
{{-- Lặp qua array các đường dẫn file đã lưu. $index là chỉ số, $path là đường dẫn --}}
|
||||
{{-- Lặp qua array các đường dẫn file đã lưu. $index là chỉ số, $path là đường dẫn --}}
|
||||
@foreach (session("stored_paths") as $index => $path)
|
||||
<div class="border p-4 mt-2">
|
||||
<p class="text-sm text-gray-600">Original Filename:
|
||||
@@ -63,6 +63,27 @@
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (count($uploads) > 0)
|
||||
<div class="container mx-auto mt-10 p-10 bg-white rounded-lg shadow-md max-w-md">
|
||||
@foreach ($uploads as $upload)
|
||||
<li class="flex items-center justify-between mb-4">
|
||||
<a class="flex items-center gap-4 py-2" href="{{ $upload->filename }}" target="_blank">
|
||||
<img src="{{ $upload->filename }}" alt="{{ $upload->filename }}" width="50" height="50">
|
||||
<span>{{ $upload->original_filename }}</span>
|
||||
</a>
|
||||
<form action="{{ route("upload.destroy", $upload->id) }}"
|
||||
method="POST"
|
||||
style="display:inline;"
|
||||
onsubmit="return confirm('Are you sure you want to delete this file?');">
|
||||
@csrf
|
||||
@method("DELETE")
|
||||
<button type="submit" class="bg-red-500 hover:bg-red-700 text-white font-bold py-2 px-4 rounded">Delete</button>
|
||||
</form>
|
||||
</li>
|
||||
@endforeach
|
||||
</div>
|
||||
@endif
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
@@ -10,3 +10,4 @@ Route::get('/', function () {
|
||||
|
||||
Route::get('/upload', [UploadController::class, 'index'])->name('upload.index');
|
||||
Route::post('/upload', [UploadController::class, 'store'])->name('upload.store');
|
||||
Route::delete('/upload/{upload}', [UploadController::class, 'destroy'])->name('upload.destroy');
|
||||
|
||||
Reference in New Issue
Block a user