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:
@@ -5,10 +5,11 @@
|
|||||||
👉 Code cho từng phần nằm ở **các branch riêng**:
|
👉 Code cho từng phần nằm ở **các branch riêng**:
|
||||||
|
|
||||||
| Phần | Tiêu đề | Branch |
|
| 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) |
|
| 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) |
|
| 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) |
|
| 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.
|
> 📖 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;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Models\Upload;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
|
||||||
@@ -14,7 +15,8 @@ class UploadController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function index()
|
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
|
// 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'
|
$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
|
$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 đó
|
// Chuyển hướng về trang trước đó
|
||||||
return back()->with('success', 'You have successfully uploaded ' . $numberOfFiles . ' files')
|
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'
|
// 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);
|
->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');
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -63,6 +63,27 @@
|
|||||||
</div>
|
</div>
|
||||||
@endif
|
@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>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -10,3 +10,4 @@ Route::get('/', function () {
|
|||||||
|
|
||||||
Route::get('/upload', [UploadController::class, 'index'])->name('upload.index');
|
Route::get('/upload', [UploadController::class, 'index'])->name('upload.index');
|
||||||
Route::post('/upload', [UploadController::class, 'store'])->name('upload.store');
|
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