diff options
| author | grothedev <grothedev@gmail.com> | 2024-12-07 13:03:32 -0600 |
|---|---|---|
| committer | grothedev <grothedev@gmail.com> | 2024-12-07 13:03:32 -0600 |
| commit | 52d4d92fb1d897ef35b22c96d9dfcbeb4b9435fb (patch) | |
| tree | 0e3b120f6812f61fdfba8d7c21859d9d1019a778 | |
| parent | 3ce6a1423db6ff78f912ccec50850512b1eb8121 (diff) | |
file browser
| -rw-r--r-- | app/Http/Controllers/SiteController.php | 39 | ||||
| -rw-r--r-- | public/main.js | 26 | ||||
| -rw-r--r-- | public/style.css | 11 | ||||
| -rw-r--r-- | resources/views/f.blade.php | 79 | ||||
| -rwxr-xr-x | resources/views/home.blade.php | 1 | ||||
| -rwxr-xr-x | routes/web.php | 9 |
6 files changed, 151 insertions, 14 deletions
diff --git a/app/Http/Controllers/SiteController.php b/app/Http/Controllers/SiteController.php index 7bcb60f..7b83d8a 100644 --- a/app/Http/Controllers/SiteController.php +++ b/app/Http/Controllers/SiteController.php @@ -4,6 +4,8 @@ namespace App\Http\Controllers; use Illuminate\Http\Request; +use Storage; + class SiteController extends Controller { /** @@ -23,4 +25,41 @@ class SiteController extends Controller public static function duneQuote(){ return '<b>todo</b>'; } + + public function uploadFiles(Request $req){ + $files = $req->file('f'); + $res = [ + 'num_files' => sizeof($files), + 'num_failed'=> 0, + 'num_uploaded' => 0, + 'success' => false, + 'files' => [] + ]; + + foreach ($files as $f){ + //validate file + /*$validated = $req->validate([ + 'f' => 'required|file|max:10240', //10MB + ]);*/ + $filename = $f->getClientOriginalName(); + if (Storage::disk('public')->fileExists($filename)){ + $filename = Carbon::now()->timestamp.'_'.$filename; + } + $path = $f->storeAs( + 'uploads', + $filename, + 'public' + ); + if ($path){ + $res['num_uploaded'] += 1; + array_push($res['files'], $path); + } else { + $res['num_failed'] += 1; + } + if (sizeof($res['num_uploaded']) == sizeof($files)){ + $res['success'] = true; + } + } + return $res; + } } diff --git a/public/main.js b/public/main.js index 8837185..c25c9d9 100644 --- a/public/main.js +++ b/public/main.js @@ -123,20 +123,20 @@ async function uploadFile() { } axios.post('/f', formData, {headers: {'Content-Type': 'multipart/form-data'}}) - .then((res)=>{ - console.log(res); - domElems.fileUploadResult.innerHTML = 'File uploaded successfully<br>'; - res.data.files.forEach((f)=>{ - domElems.fileUploadResult.innerHTML += `<a href = "f/${f.filename}">${f.filename}</a><br>`; + .then((res)=>{ + console.log(res); + domElems.fileUploadResult.innerHTML = 'File uploaded successfully<br>'; + res.data.files.forEach((f)=>{ + domElems.fileUploadResult.innerHTML += `<a href = "f/${f.filename}">${f.filename}</a><br>`; + }); + domElems.inputFile.value = null; + domElems.buttonFileUpload.enabled = true; + }) + .catch((err)=>{ + console.log(err); + domElems.fileUploadResult.innerHTML = 'Error uploading file'; + domElems.buttonFileUpload.enabled = true; }); - domElems.inputFile.value = null; - domElems.buttonFileUpload.enabled = true; - }) - .catch((err)=>{ - console.log(err); - domElems.fileUploadResult.innerHTML = 'Error uploading file'; - domElems.buttonFileUpload.enabled = true; - }); } async function uploadFileChunked(f){ diff --git a/public/style.css b/public/style.css index f92d792..6c533ba 100644 --- a/public/style.css +++ b/public/style.css @@ -48,6 +48,17 @@ header { min-width: 200px; } +footer { + position: relative; + padding: 8px 12px 12px; + margin: auto; + box-shadow: 0 0 10px rgba(0,0,0,0.1); + height: 100%; + display: block; + max-width: 800px; + min-width: 100px; +} + li a { color: #2e3f25; text-decoration: none; diff --git a/resources/views/f.blade.php b/resources/views/f.blade.php new file mode 100644 index 0000000..9cad1de --- /dev/null +++ b/resources/views/f.blade.php @@ -0,0 +1,79 @@ +@extends('template') +<?php + $baseDir = 'storage/uploads/'; + $currentDir = $baseDir; + + //use this if want to require auth + /*$valid_username = 'admin'; // Set your username + $valid_password = 'password'; // Set your password + if (!isset($_SERVER['PHP_AUTH_USER']) || !isset($_SERVER['PHP_AUTH_PW']) || + $_SERVER['PHP_AUTH_USER'] != $valid_username || $_SERVER['PHP_AUTH_PW'] != $valid_password) { + header('WWW-Authenticate: Basic realm="Secure Directory"'); + header('HTTP/1.0 401 Unauthorized'); + echo 'Authentication required'; + exit; + }*/ + + // check if requested file or directory + if (isset($_GET['file'])) { + $fileRequested = $_GET['file']; + $filePath = realpath($fileRequested); + + if (file_exists($filePath) && is_file($filePath)) { + // Set headers to force download + header('Content-Description: File Transfer'); + header('Content-Type: application/octet-stream'); + header('Content-Disposition: attachment; filename="' . basename($filePath) . '"'); + header('Expires: 0'); + header('Cache-Control: must-revalidate'); + header('Pragma: public'); + header('Content-Length: ' . filesize($filePath)); + readfile($filePath); + exit; + } else { + echo "File not found."; + exit; + } + } else if (isset($_GET['dir'])) { + $dir = $_GET['dir']; + if (strpos($dir, '..') !== false || strpos($dir, '/') !== false || strpos($dir, '\\') !== false) { + echo 'Access Denied'; + exit; + } + $dir= basename($dir); // Ensuring the folder name is isolated + if (!is_dir("${baseDir}/${dir}")) { + echo 'Directory not found'; + exit; + } + $currentDir = "${baseDir}/${dir}"; + } + + // Extracting the name of the current directory + $currentDirName = basename($currentDir); + + // Determine the depth of the current directory relative to the base directory + $depth = substr_count(str_replace($baseDir, '', $currentDir), '/'); + + $contents = scandir($currentDir); +?> +@section('body') +<main> + <p><b>Contents of:</b> <em> {{ $currentDir }}</em></p> + <p><b>{{ htmlspecialchars(ucfirst($currentDirName)) }}</b></p> + <ul> + @foreach ($contents as $item) + @if ($item !== "." && $item !== "..") + <li> + @if (is_dir($currentDir . '/' . $item)) + <strong>Directory:</strong> <a href="?dir={{ $item }}">{{ htmlspecialchars($item) }}</a> + @else + <a href="/f?file={{ $currentDir }}/{{ $item }}">{{ htmlspecialchars($item) }}</a> + @endif + </li> + @endif + @endforeach + @if ($currentDir != $baseDir) + <li><a href="/f?dir={{ $currentDirName }}">Go Up</a></li> + @endif +</main> +@endsection
\ No newline at end of file diff --git a/resources/views/home.blade.php b/resources/views/home.blade.php index 4ac84e9..863f0de 100755 --- a/resources/views/home.blade.php +++ b/resources/views/home.blade.php @@ -31,6 +31,7 @@ <section id = "fileupload-nojs"> <h4>File Upload (under construction)</h4> <form action="/f" method="POST" enctype="multipart/form-data"> + @csrf <input multiple name="f[]" type="file"> <button type = "submit">Upload</button> </form> diff --git a/routes/web.php b/routes/web.php index cdd8e4f..c450da5 100755 --- a/routes/web.php +++ b/routes/web.php @@ -11,4 +11,11 @@ Route::get('/env', [SiteController::class, 'env']); Route::get('/dq', [SiteController::class, 'duneQuote']); -Route::post('/f', [SiteController::class, 'fileUpload']); //TODO later use file resource or FPR service
\ No newline at end of file +Route::post('/f', [SiteController::class, 'uploadFiles']); //TODO later use file resource or FPR service +Route::get('/f/{path}', function($path){ + return response()->file(storage_path('/public/uploads/' . $path)); +}); + +Route::get('/{v}', function($v){ + return view($v); +});
\ No newline at end of file |
