From 34adca20d5834fb11d8ab4fc677e485c7ab9bde9 Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 5 Feb 2025 22:23:24 +0200 Subject: [PATCH] upload file (chunks) complete --- .DS_Store | Bin 10244 -> 14340 bytes .gitignore | 1 + app/.DS_Store | Bin 8196 -> 10244 bytes .../Filemanager/GetFileContentsAction.php | 1 + app/Actions/Filemanager/UploadFileAction.php | 44 ++++++++++++++ .../Controllers/FilemanagerController.php | 8 +++ database/.DS_Store | Bin 6148 -> 6148 bytes public/.DS_Store | Bin 6148 -> 6148 bytes .../Filemanager/Components/UploadFile.jsx | 57 ++++++++++++++++++ .../js/Pages/Filemanager/Filemanager.jsx | 11 +++- routes/web.php | 1 + 11 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 app/Actions/Filemanager/UploadFileAction.php create mode 100644 resources/js/Pages/Filemanager/Components/UploadFile.jsx diff --git a/.DS_Store b/.DS_Store index 79b194b2ddcf92dcfab477e58e4c53f1686804e8..79e8c00c9ca68760ff2dd71340374a0318e6b0c2 100644 GIT binary patch literal 14340 zcmeHN-)|d55T1*h#BS0wg%-gB#Rw!MlmE{6wkd6y{3rE>6lK8+)WCl1c@IB`Erv`jVHMPoP* z8r0^49z0_HO*pqxm9iRtmU2|00=Hh9=SuEEuH@#xg9>RcM7;Bt97O)} z_($g!?!W!ncX$WcqqImxs#TZLa|>>{if2Smej`P6i4ceoh!BVnh!FT6BEV}ej`)CA zM%M^|2!RNJCIUP^Byn;%?U!p_DN_e7?85VVcH!l~J-g-nEa{iie!1qAc!R_7SW$Yc zjvrz;9y^{VeY$DCT=PngogAqda{QVdKSFV&c05lCIXTl_8C@d;A_PnX_TteFE%r`H z^xjqU?L3Sb;EhJ~ZAeOoko0~>NnS>wyEfhGC@Ir@n|c;IN*WI#>Bo+eCc2jt+t*Rj zWcQLdbJFv@b?kPBkn}}INqf4NB>H4;(^LpatWT;WHNO->2MB#@<(C2)oM|6{*LmW+;TM@Yr>b6v9?mFEvT3 zHihUL%h9w+l@p?84z$}UCrrOES6bzSm;qQLt#U%xKkK7aP6+E~ZPerpV1--4S*Hr; zf{_zGgF3y0%-;82BtpZ)#>=WQ%1;F$;}W>jgdVUQm|W{s%8-4&7>usZyWX zavP1-W{F0rUrf_Q%d;@Yf<6MWaI38jP;2duPai_N0~Bh@kAK}n-k@sfqn%1?{pO>n zjPAp^*y8lw$zq|lxsOhQj*)~;=(G+m zbXHomhp`KA>DV3=S!y3Yzdkznx@Us{npQ7uG-^M4AD2YM5bEItsj&X&%Ob1xVF;SD z1bleQm0eJtjrcwfX@RB9aASMuG#v|I6m%+h9HQetjsP#h%{_9}5NPMQs`^eff_D4s z>LlLoy{i2F{`({F<|inF?*(?#qbWX#Ek4YUt?~XlL)mVM1d+ygwj>E5; zNPB+WSPFjKSZV`)o!^~+C&eJj>;v$4PAl6$GzN?1RjH~&&7KF1DxQZ=bToww0x|BY&MH=lTZ>kiL(YQAkPIp$l<-eQp1lo}Yc0YJ}gX9cAn;rqr;cOQ;yZ4#$E#4{?OZ?uo>M_!q!JqDobX+i|j^vp^?w6xnIfFzHj{Pn}kx zNwpS@R!8pImyoNyS26o=^hP7d2+*|9ve9Tbd0}B(+RUR4rv%PPT5q>R>gqgc(04TU z{<|0n$Nfn74$YWG#|$%Mg=zqmX}|awW*EnO%N`&vb6HkI9bTr_RLG$32=Bir(O`5; z*ZGle0fa%L>iw0Mn|j}duBH2(=rsMOHB@QV85s7h+Jd=DX5d}06dqK}D*A9rnAZH- z5z>b>?gBVkzcz^s34>JrA@CPbXBL*p-&pcI#(Az4dNUY87^;^5Zymg4dJ7zqU(;J_ zWCgjl2FHA7FH34uTe^j_ZR-4In{OrcqRxbaSlL{`X&!CmySjLHfe=`n4K@2`h=v9r|c2z=3&RS-9HNh2W5sa+Ay4Voo;806e z4F)9GRyJOuNdLf(HVE)!FiSsDV z#sOL($3;HHLn)u);SYa`x2HkJCEiW@<(gLtE1nB0N?}FmeZ_azJ_6J-5NgIUivJrM mueR7;MaxE`dZRq(IE=7Yj}Z)?&7kiXphodO!kLZ5|9=BoUuA{> delta 233 zcmZoEXbF&DU|?W$DortDU{C-uIe-{M3-C-V6q~3gIoZI3MH0wo&<0{gpg03V5(s+c zTPY!+nv#x_}jaqVVy4i*kZ?a7Z6vNuO4nK4fOr@VA>t*Xf6aMhm4v(*GQ*QjMM zO|H@Go$RXhVDeq}aCIsR2>~hM*`d?eq#UfDor$AIelw1ipg#Zw4}5nmXH{qdt-sI=Xa+O`ngPv#X5b_+fbVQ} z7z4uURx_X(&HZrli9qqEn)fAfelXq&}Q&!e&99c0o=!wHZN^USni7V6xjoj zu0*C7M7U$W$>3=7(zb*Z?m&b)5IHiD84BT}qo2v)K=Q)sRx_X(NHV~3_kNg%3IyOp z^Y>a^fG_<_B5Jf)EW5OfJ;u|@nX@DBKhLM3s)s<;*IBioJsKah9~ML;*t%ffaA`%3 zhKrl9c*cM81Fu;03cB3%>k|F3Tz4Hmn3(uVdU`Xb`uYvS7%*0>b=tIoQn2Y4N{waq z=`N*ixqV$K-*fEd>d^24^@5V)*$wXCRBePjTynfBZ5HUJSM|BCB|403HoH1>ZhL!X za%#++oSWJiGq-cOxw$cOc4m5KCu@w1UcGi_b;GTB^f?b4h}_FyP<#&C-Q=`HQKe1O z`4>qhB2lhJJBADRN@xDzWU%6ZoO5E%#E*R_z-(o6s*dx;UQM( zkH-Jzbr^pP(}}zrMvd9TVUVrc$RovF$l;MAr|M%)E+8tp52bkgFAsdm)KqE6emZ4Q zfyM`a?X8HNDdm3A{pnz&Di*%NQ^krc5d$o~FqoVbyo!s-UZGJj6L@vLGhYy&z(i+z z@zcxiws>Wx;5v`wK{$1$EgVuGngPv#WJ#+GtlX5l| zPGg_gz`L29gN1{UZ}S`hamLNgLb8mTUkD2_@{|P^<>ln(rGs=%mKD>V%qA|p`MDS` xlBwRuEZ7lrGJegl5kOOEN$Q2Bm<9X&V0{}}PAe{gJ diff --git a/app/Actions/Filemanager/GetFileContentsAction.php b/app/Actions/Filemanager/GetFileContentsAction.php index d790e49..97098a6 100644 --- a/app/Actions/Filemanager/GetFileContentsAction.php +++ b/app/Actions/Filemanager/GetFileContentsAction.php @@ -36,6 +36,7 @@ class GetFileContentsAction 'text/x-typescript', // .ts, .tsx 'text/x-jsx', // .jsx, .tsx 'application/x-sh', // .sh + 'application/x-sql', // .sql ]; diff --git a/app/Actions/Filemanager/UploadFileAction.php b/app/Actions/Filemanager/UploadFileAction.php new file mode 100644 index 0000000..294b6bf --- /dev/null +++ b/app/Actions/Filemanager/UploadFileAction.php @@ -0,0 +1,44 @@ +validate([ + 'file' => 'required|file', + 'chunkIndex' => 'required|integer|min:0', + 'totalChunks' => 'required|integer|min:1', + 'originalName' => 'required|string|max:255', + 'path' => 'required|string', + ]); + + $file = $r->file('file'); + + $path = $this->path . '/' . $r->path; + + File::append($path . '/' . $r->originalName, $file->get()); + + /* $handle = fopen($file->getPathname(), 'rb'); */ + /* $destination = fopen($path . '/' . $r->originalName, 'ab'); */ + /**/ + /* if ($handle && $destination) { */ + /* stream_copy_to_stream($handle, $destination); // Append chunk data */ + /* fclose($handle); */ + /* fclose($destination); */ + /* } */ + + return response()->json([ + 'message' => 'Chunk uploaded', + 'chunkIndex' => $r->chunkIndex, + 'totalChunks' => $r->totalChunks, + 'toDestination' => $path . '/' . $r->originalName + ]); + } +} diff --git a/app/Http/Controllers/FilemanagerController.php b/app/Http/Controllers/FilemanagerController.php index aebf82c..5df9ef5 100644 --- a/app/Http/Controllers/FilemanagerController.php +++ b/app/Http/Controllers/FilemanagerController.php @@ -12,12 +12,14 @@ use App\Actions\Filemanager\GetDirectoryContentsAction; use App\Actions\Filemanager\GetFileContentsAction; use App\Actions\Filemanager\RenameFileAction; use App\Actions\Filemanager\UpdateFileContentsAction; +use App\Actions\Filemanager\UploadFileAction; use League\Flysystem\UnixVisibility\PortableVisibilityConverter; use Illuminate\Http\StreamedResponse; class FilemanagerController extends Controller { public Filesystem $filesystem; + public string $path; public function __construct() { @@ -26,6 +28,7 @@ class FilemanagerController extends Controller $adapter = new LocalFilesystemAdapter($path, null, LOCK_EX, LocalFilesystemAdapter::DISALLOW_LINKS); $this->filesystem = new Filesystem($adapter); + $this->path = $path; } public function index() @@ -62,4 +65,9 @@ class FilemanagerController extends Controller { return (new DeleteFilesAction($this->filesystem))->execute($r); } + + public function uploadFile(Request $r) + { + return (new UploadFileAction($this->path))->execute($r); + } } diff --git a/database/.DS_Store b/database/.DS_Store index b2313cadb4ad0198df1da2d894ddd85b930f488c..4c2883b25521b0b9c299c52f30018351a7eae8b0 100644 GIT binary patch delta 469 zcmZoMXfc=|#>B!ku~2NHo+6{*#(>?7i#IScF$zxRVKS}fWJqI3WJqQxVaR7FV#s7j zWhl-`Hw;eB&n;j80~TW-g+*0vzKcszPJR+lmSeH~m+Xk;#~g8~Ou?yA7S-y43}mYX zCKobEZVqD-WE4Pk6W^}M{>&00$WCzZgE#>yfv^!-f*;j<1CaTX)0u7S*%^v~K2K#x z0pcR`5MVq3^cR{6WUH44!+npT3gHgistPiAQG7kIuzxc<2R{ce(l#$-{?0s^U&N7v Qk%55;=nRI<5h81t0esB)qu~2NHo+2ab#(>?7jI5LGSi~kPvB*yrWfk50jYW`g@_IJg&0-va mEE5}oHnVf^a{#q$7UcNOJegm_k%IvU7#SE?Hb;o8VFmzn6%%a$ diff --git a/public/.DS_Store b/public/.DS_Store index 3568b76eda30dd8eb55c6a8dfecc66752cc04851..ada1f43f2c24ece5c785c2850a33175c87de5ae1 100644 GIT binary patch delta 289 zcmZoMXfc@J&nUDpU^g?P&}JSMZpQkYbi?4}{M-Tt5a7(X10-1)k{C)EG8u9hQgZWM zT#|C~lYpWeHEShHYgZg|L|2hQKt(|Yk_}uFfZCC4*eu2x%~-D`Q3MuEW5{R7V<=%L zMz(iS-Iwf$#c8 { + + const [file, setFile] = useState(null); + const [progress, setProgress] = useState(0); + + const uploadFile = async () => { + if (!file) return; + + const totalChunks = Math.ceil(file.size / CHUNK_SIZE); + let uploadedChunks = 0; + + for (let chunkIndex = 0; chunkIndex < totalChunks; chunkIndex++) { + const start = chunkIndex * CHUNK_SIZE; + const end = Math.min(start + CHUNK_SIZE, file.size); + const chunk = file.slice(start, end); + + const formData = new FormData(); + formData.append("file", chunk); + formData.append("chunkIndex", chunkIndex); + formData.append("totalChunks", totalChunks); + formData.append("originalName", file.name); + formData.append("path", path); + + await axios.post("/filemanager/upload-file", formData); + + uploadedChunks++; + setProgress(Math.round((uploadedChunks / totalChunks) * 100)); + } + + refreshFiles(path); + setShowUploadFile(false); + toast('File uploaded successfully', { type: 'success' }); + }; + + return ( + setShowUploadFile(false)}> +
+ setFile(e.target.files[0])} /> + Upload + setShowUploadFile(false)}>Cancel +

Upload Progress: {progress}%

+
+
+ ); +} + +export default UploadFile; diff --git a/resources/js/Pages/Filemanager/Filemanager.jsx b/resources/js/Pages/Filemanager/Filemanager.jsx index b0c37c0..4268b6e 100644 --- a/resources/js/Pages/Filemanager/Filemanager.jsx +++ b/resources/js/Pages/Filemanager/Filemanager.jsx @@ -11,6 +11,7 @@ import CreateFile from './Components/CreateFile'; import EditFile from './Components/EditFile'; import DeleteFiles from './Components/DeleteFiles'; import RenameFile from './Components/RenameFile'; +import UploadFile from './Components/UploadFile'; import { LuFolderPlus } from "react-icons/lu"; import { LuFilePlus2 } from "react-icons/lu"; @@ -35,6 +36,7 @@ const Filemanager = () => { const [editFile, setEditFile] = useState(false); const [showConfirmDelete, setShowConfirmDelete] = useState(false); const [renameFile, setRenameFile] = useState(false); + const [showUploadFile, setShowUploadFile] = useState(false); useEffect(() => { cdIntoPath(path); @@ -159,7 +161,7 @@ const Filemanager = () => {
- @@ -296,6 +298,13 @@ const Filemanager = () => { path={path} /> + + ); } diff --git a/routes/web.php b/routes/web.php index 3e296a2..ec4ac98 100644 --- a/routes/web.php +++ b/routes/web.php @@ -28,6 +28,7 @@ Route::patch('/filemanager/update-file-contents', [FilemanagerController::class, Route::post('/filemanager/create-file', [FilemanagerController::class, 'createFile'])->middleware(['auth'])->name('filemanager.createFile'); Route::patch('/filemanager/rename-file', [FilemanagerController::class, 'renameFile'])->middleware(['auth'])->name('filemanager.renameFile'); Route::post('/filemanager/delete-files', [FilemanagerController::class, 'deleteFiles'])->middleware(['auth'])->name('filemanager.deleteFiles'); +Route::post('/filemanager/upload-file', [FilemanagerController::class, 'uploadFile'])->middleware(['auth'])->name('filemanager.uploadFile'); // Stats History Route::get('/stats/history', [StatsHistoryController::class, 'cpuAndMemory'])->middleware(['auth', AdminMiddleware::class])->name('stats.history');