first commit

This commit is contained in:
2025-05-02 01:32:22 +03:00
commit 0311b21d23
5 changed files with 195 additions and 0 deletions

75
README.md Normal file
View File

@@ -0,0 +1,75 @@
# Minimal Chunked File Storage (PHP)
This is a minimalistic PHP-based file storage system with:
* Password-protected admin panel
* Chunked file upload for large files (GB+)
* Upload progress display
* File listing with download and delete options
* Direct link copy button
* No external libraries required
## 🚀 Features
* Chunked upload via JavaScript + `fetch`
* Server-side chunk handling and merging
* No CSS or frontend frameworks
* Fully self-contained (no Composer needed)
## 🛠 Requirements
* PHP 7.4+
* A web server (or use PHP's built-in server)
## 📁 Folder Structure
```
/simple-file-share/
├── index.php
├── upload/ # Final uploaded files
├── upload_chunks/ # Temporary chunk storage
├── upload_chunk.php
├── merge_chunks.php
└── config.php # Configuration (password and paths)
```
## 🔐 Configuration
Create `config.php`:
```php
<?php
define('PASSWORD', 'your_password_here');
define('UPLOAD_DIR', __DIR__ . '/upload/');
define('CHUNK_DIR', __DIR__ . '/upload_chunks/');
```
## ▶️ Run the Server
Use PHP's built-in server:
```bash
php -S localhost:8000
```
Then open:
```
http://localhost:8000
```
## 📤 Uploading Files
* Select a file in the UI.
* It is split into 1MB chunks (adjustable in JS).
* Upload progress is shown.
* File is merged server-side and available for download.
## 🧹 Cleanup
* Temporary chunk files are automatically deleted after merging.
* Files can be deleted via the admin interface.
## 📝 License
This project is public domain / MIT use freely.

4
config.php Normal file
View File

@@ -0,0 +1,4 @@
<?php
define('PASSWORD', 'your_password_here');
define('UPLOAD_DIR', __DIR__ . '/upload/');
define('CHUNK_DIR', __DIR__ . '/upload_chunks/');

87
index.php Normal file
View File

@@ -0,0 +1,87 @@
<?php
session_start();
require_once __DIR__ . '/config.php';
if (!file_exists(UPLOAD_DIR)) mkdir(UPLOAD_DIR);
if (!file_exists(CHUNK_DIR)) mkdir(CHUNK_DIR);
if (!isset($_SESSION['logged_in']) || ($_GET['action'] ?? '') === 'logout') {
if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['password'] ?? '') === PASSWORD) {
$_SESSION['logged_in'] = true;
header("Location: index.php");
exit;
}
echo '<form method="post">
<h3>Login</h3>
<input type="password" name="password" placeholder="Password">
<button type="submit">Login</button>
</form>';
exit;
}
// Удаление
if (isset($_GET['delete'])) {
$f = basename($_GET['delete']);
@unlink(UPLOAD_DIR . $f);
header("Location: index.php");
exit;
}
$files = array_diff(scandir(UPLOAD_DIR), ['.', '..']);
?><!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>Файловое хранилище</title></head>
<body>
<h3>Файловое хранилище</h3>
<p><a href="?action=logout">Выйти</a></p>
<input type="file" id="fileInput">
<div id="progress"></div>
<ul>
<?php foreach ($files as $file): $url = 'upload/' . rawurlencode($file); ?>
<li>
<?= htmlspecialchars($file) ?>
[<a href="<?= $url ?>" target="_blank">Скачать</a>]
[<a href="?delete=<?= urlencode($file) ?>" onclick="return confirm('Удалить?')">Удалить</a>]
<button onclick="copyLink('<?= $url ?>')">Копировать ссылку</button>
</li>
<?php endforeach; ?>
</ul>
<script>
function copyLink(link) {
navigator.clipboard.writeText(location.origin + '/' + link).then(() => alert("Скопировано"));
}
const input = document.getElementById('fileInput');
input.addEventListener('change', async () => {
const file = input.files[0];
if (!file) return;
const chunkSize = 1024 * 1024; // 1MB
const totalChunks = Math.ceil(file.size / chunkSize);
for (let i = 0; i < totalChunks; i++) {
const chunk = file.slice(i * chunkSize, (i + 1) * chunkSize);
const formData = new FormData();
formData.append('chunk', chunk);
formData.append('filename', file.name);
formData.append('index', i);
formData.append('total', totalChunks);
await fetch('upload_chunk.php', { method: 'POST', body: formData });
document.getElementById('progress').innerText = `Загружено: ${i+1}/${totalChunks}`;
}
await fetch('merge_chunks.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ filename: file.name, total: totalChunks })
});
alert('Готово!');
location.reload();
});
</script>
</body>
</html>

21
merge_chunks.php Normal file
View File

@@ -0,0 +1,21 @@
<?php
require_once __DIR__ . '/config.php';
$data = json_decode(file_get_contents('php://input'), true);
$filename = basename($data['filename']);
$total = intval($data['total']);
$tmpDir = __DIR__ . '/upload_chunks/' . $filename;
$finalPath = __DIR__ . '/upload/' . $filename;
$out = fopen($finalPath, 'w');
for ($i = 0; $i < $total; $i++) {
$partPath = "$tmpDir/$i.part";
$in = fopen($partPath, 'r');
stream_copy_to_stream($in, $out);
fclose($in);
unlink($partPath);
}
fclose($out);
rmdir($tmpDir);
http_response_code(200);

8
upload_chunk.php Normal file
View File

@@ -0,0 +1,8 @@
<?php
$filename = basename($_POST['filename']);
$index = intval($_POST['index']);
$tmpDir = __DIR__ . '/upload_chunks/' . $filename;
if (!file_exists($tmpDir)) mkdir($tmpDir, 0777, true);
move_uploaded_file($_FILES['chunk']['tmp_name'], "$tmpDir/$index.part");