Upload files to "public"

This commit is contained in:
MaciejkaG 2024-01-15 20:37:43 +01:00
commit 7a9e6fd1d6
5 changed files with 365 additions and 0 deletions

35
public/create-folder.php Normal file
View File

@ -0,0 +1,35 @@
<?php
function join_paths() {
$paths = array();
foreach (func_get_args() as $arg) {
if ($arg !== '') { $paths[] = $arg; }
}
return preg_replace('#/+#','/',join('/', $paths));
}
$request_body = file_get_contents('php://input');
$data = json_decode($request_body);
$filesDir = "../../files/"; // Musi kończyć się slashem!
$redirectRoute = "/pen"; // Adres względny do któego ma przekierować, jeżeli masz index.php w public/upload to powinno być to /upload
$targetName = $data->name;
$targetPath = $data->path;
$fullTargetPath = join_paths($filesDir, $targetPath, $targetName);
if (!file_exists($fullTargetPath)) {
if (mkdir($fullTargetPath)) { // Skopiuj zuploadowany plik do poprawnego miejsca na serwerze
http_response_code(200);
header('Location: '.$redirectRoute); // Przekieruj z powrotem do strony głównej
} else { // W razie gdyby coś nie wyszło po stronie serwera podczas kopiowania pliku
http_response_code(500);
echo "500 - Sorry, there was an error creating your folder.";
}
} else {
http_response_code(409);
echo "409 - File already exists";
}
?>

29
public/file.php Normal file
View File

@ -0,0 +1,29 @@
<?php
function join_paths() {
$paths = array();
foreach (func_get_args() as $arg) {
if ($arg !== '') { $paths[] = $arg; }
}
return preg_replace('#/+#','/',join('/', $paths));
}
$filesDir = "../../files/"; // Musi kończyć się slashem!
$dirList = preg_grep('/^([^.])/', scandir($filesDir)); // Skanuj
if (in_array($_GET['name'], $dirList) && file_exists(join_paths($filesDir, $_GET['name']))) {
header('Content-Description: File Transfer'); // Ustaw headery które będą pokazywać przeglądarce, że zasób jest plikiem do pobrania, oraz będą wysyłać metadane pliku
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' . basename(join_paths($filesDir, $_GET['name'])));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize(join_paths($filesDir, $_GET['name'])));
ob_clean();
flush(); // Wyczyść bufer outputu, żeby nie obciążać pliku
readfile(join_paths($filesDir, $_GET['name'])); // Zwróć plik do klienta
exit;
} else { http_response_code(404); echo "<h1>404 - Not Found (Requested file not found)</h1>"; }
?>

186
public/index.php Normal file
View File

@ -0,0 +1,186 @@
<?php
function join_paths() {
$paths = array();
foreach (func_get_args() as $arg) {
if ($arg !== '') { $paths[] = $arg; }
}
return preg_replace('#/+#','/',join('/', $paths));
}
$filesDir = "../../files/"; // Musi kończyć się slashem!
$maxFolderSize = 250000000; // Maks. rozmiar folderu z plikami (w bajtach)
$directorySize = getDirectorySize($filesDir);
if (isset($_GET["path"])) {
$path = $_GET["path"];
if (is_dir(join_paths($filesDir, $path)) && !str_contains($path, "../")) {
$filesDir = join_paths($filesDir, $path);
}
} else {
header('Location: '."?path=/");
}
$dirList = preg_grep('/^([^.])/', scandir($filesDir)); // Pobierz listę plików z pominięciem nazw zaczętych kropką ('.')
function formatBytes($bytes, $precision = 2) {
$units = array('B', 'KB', 'MB', 'GB', 'TB');
$bytes = max($bytes, 0);
$pow = floor(($bytes ? log($bytes) : 0) / log(1024));
$pow = min($pow, count($units) - 1);
$bytes /= pow(1024, $pow);
return round($bytes, $precision) . $units[$pow];
}
function getDirectorySize($path){
$bytestotal = 0;
$path = realpath($path);
if($path!==false && $path!='' && file_exists($path)){
foreach(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS)) as $object){
$bytestotal += $object->getSize();
}
}
return $bytestotal;
}
?>
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Upload service</title>
<link rel="stylesheet" href="style.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;700&family=Quicksand:wght@400;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0,0" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
</head>
<body>
<div class="box">
<div class="pobieranie">
<h1>Udostępnij plik</h1>
<button id="uploadButton">Prześlij plik</button>
<h3>Zajęte miejsce: <?php echo formatBytes($directorySize)."/".formatBytes($maxFolderSize); ?> (<?php echo round($directorySize / $maxFolderSize * 100, 2); ?>%)</h3>
<h2 class="path"><?php echo $path; ?></h2>
<h3><a href="?path=<?php echo dirname($path); ?>">Wróć </a> | <a href="#" onclick="createFolderPrompt()">Utwórz folder</a></h3>
<p>
<div class="pliki">
<?php
if (empty($dirList)) { // Wyświetl ładną wiadomość, jeśli lista plików jest pusta
echo "Nothing to see here (yet)";
} else {
foreach ($dirList as $fName) {
$uriFname = urlencode($fName);
if (is_dir(join_paths($filesDir, $fName))) {
// Folder
echo "<div class=\"plik folder\"><a href=\"?path=".join_paths($path, $uriFname)."\" class=\"name\"><span class=\"material-symbols-outlined\">folder</span> $fName</a><a href=\"#\" data-path=\"".join_paths($path, $uriFname)."\" class=\"delete\"><span class=\"material-symbols-outlined\">delete</span></a><br></div>"; // Pętla wyświetlająca każdy element z $dirList w formie linku
} else {
// Plik
echo "<div class=\"plik\"><a href=\"file.php?name=".join_paths($path, $uriFname)."\" target=\"_blank\" class=\"name\"><span class=\"material-symbols-outlined\">draft</span> $fName</a><a href=\"#\" data-path=\"".join_paths($path, $uriFname)."\" class=\"delete\"><span class=\"material-symbols-outlined\">delete</span></a><br></div>"; // Pętla wyświetlająca każdy element z $dirList w formie linku
}
}
}
?>
</div>
</p>
</div>
<script>
const params = new URLSearchParams(window.location.search);
function createFolderPrompt() {
let folderName = prompt("Podaj nazwę nowego folderu");
if (folderName!==null) {
$.ajax({
url: "create-folder.php", type: "POST", contentType: 'application/json', data: JSON.stringify({ name: folderName, path: params.get('path') }), success: function () {
window.location.reload();
},
error: function() {
window.location.reload();
}
});
} else {
setTimeout(() => {
lockButtons(false);
}, 1);
}
}
async function upload() {
const formData = new FormData();
formData.append("path", params.get('path'));
const selection = await window.showOpenFilePicker({multiple: false});
if (selection.length > 0) {
const file = await selection[0].getFile();
formData.append("file", file);
}
try {
const response = await fetch("upload.php", {
method: "POST",
body: formData,
});
window.location.reload();
} catch (e) {
console.error(e);
}
}
async function remove(name) {
const formData = new FormData();
formData.append("name", name);
try {
const response = await fetch("remove.php", {
method: "POST",
body: formData,
});
window.location.reload();
} catch (e) {
console.error(e);
}
}
function lockButtons(state) {
if (state) {
$(".pliki").css({
opacity: 0.25,
"pointer-events": "none",
});
$("a").css("pointer-events", "none");
} else {
$(".pliki").css({
opacity: 1,
"pointer-events": "all",
});
$("a").css("pointer-events", "all");
}
}
$("a").on("click", function () {
lockButtons(true);
});
$("#uploadButton").on("click", upload);
$(".delete").on("click", async function () {
await remove($(this).data("path"));
})
</script>
</div>
</body>
</html>

85
public/style.css Normal file
View File

@ -0,0 +1,85 @@
body {
font-family: 'Quicksand', sans-serif;
background: rgb(242, 242, 242);
}
.pobieranie {
padding: 40px;
font-family: 'Quicksand', sans-serif;
}
.box {
display: flex;
justify-content: center;
font-family: 'Quicksand', sans-serif;
}
.pliki {
line-height: 25px;
width: 500px;
max-width: 100vw;
display: flex;
flex-direction: column;
justify-content: center;
transition: opacity 0.3s;
}
input {
font-family: 'Quicksand', sans-serif;
}
.pliki a {
color: black;
}
.pliki .plik {
display: flex;
margin-bottom: 10px;
}
.plik .name, .plik .delete {
padding: 7px 12px;
display: flex;
justify-content: center;
align-items: center;
transition: all 0.2s;
}
.pliki .plik .name {
background: white;
display: flex;
align-items: center;
justify-content: flex-start;
gap: 5px;
flex: 1;
border-top-left-radius: 20px;
border-bottom-left-radius: 20px;
border-right: rgb(208, 208, 208) solid 1px;
text-decoration: none;
}
.pliki .plik .name:hover {
background: rgb(72, 91, 255);
color: white;
}
.pliki .plik .delete {
background: white;
color: red;
border-top-right-radius: 20px;
border-bottom-right-radius: 20px;
text-decoration: none;
}
.pliki .plik .delete:hover {
background: red;
color: white;
}
.path {
border-radius: 10px;
font-family: 'Fira Code', monospace;
padding: 3px 5px;
font-size: 17px;
border: black 1px solid;
}

30
public/upload.php Normal file
View File

@ -0,0 +1,30 @@
<?php
function join_paths() {
$paths = array();
foreach (func_get_args() as $arg) {
if ($arg !== '') { $paths[] = $arg; }
}
return preg_replace('#/+#','/',join('/', $paths));
}
$filesDir = "../../files/"; // Musi kończyć się slashem!
$redirectRoute = "/pen"; // Adres względny do któego ma przekierować, jeżeli masz index.php w public/upload to powinno być to /upload
if (isset($_POST["path"])) { // Jeżeli to faktycznie jest formularz i zawiera ścieżke do kopiowania pliku
$targetFile = join_paths($filesDir, $_POST["path"], basename($_FILES["file"]["name"]));
if (!file_exists($targetFile)) {
if (move_uploaded_file($_FILES["file"]["tmp_name"], $targetFile)) { // Skopiuj zuploadowany plik do poprawnego miejsca na serwerze
http_response_code(200);
} else { // W razie gdyby coś nie wyszło po stronie serwera podczas kopiowania pliku
http_response_code(500);
echo "Sorry, there was an error uploading your file.";
}
} else {
http_response_code(409);
echo "409 - Resource already exists (file already exists)";
}
}
?>