admin panel added
This commit is contained in:
commit
534a84e51a
|
@ -0,0 +1,5 @@
|
|||
module upload
|
||||
|
||||
go 1.22.4
|
||||
|
||||
require github.com/google/uuid v1.6.0 // indirect
|
|
@ -0,0 +1,2 @@
|
|||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
|
@ -0,0 +1,49 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Admin Panel</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Admin Panel</h1>
|
||||
<form id="adminForm">
|
||||
<label for="maxSize">Max File Size:</label>
|
||||
<input type="number" id="maxSize" name="maxSize" required>
|
||||
<select id="sizeUnit" name="sizeUnit">
|
||||
<option value="MB">MB</option>
|
||||
<option value="GB">GB</option>
|
||||
</select><br><br>
|
||||
|
||||
<label for="lifetime">Link Lifetime:</label>
|
||||
<input type="number" id="lifetime" name="lifetime" required><br><br>
|
||||
|
||||
<button type="button" onclick="generateLink()">Generate</button>
|
||||
</form>
|
||||
<p id="uploadLink"></p>
|
||||
|
||||
<script>
|
||||
async function generateLink() {
|
||||
const maxSize = document.getElementById('maxSize').value;
|
||||
const sizeUnit = document.getElementById('sizeUnit').value;
|
||||
const lifetime = document.getElementById('lifetime').value;
|
||||
|
||||
const response = await fetch('/generate', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ maxSize, sizeUnit, lifetime })
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
document.getElementById('uploadLink').innerText = `Upload Link (copied to clipboard): ${data.uploadLink}`;
|
||||
navigator.clipboard.writeText(data.uploadLink);
|
||||
} else {
|
||||
document.getElementById('uploadLink').innerText = 'Error generating link';
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,45 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Chunked File Upload</title>
|
||||
</head>
|
||||
<body>
|
||||
<input type="file" id="fileInput">
|
||||
<button onclick="uploadFile()">Upload</button>
|
||||
|
||||
<script>
|
||||
async function uploadFile() {
|
||||
const fileInput = document.getElementById('fileInput');
|
||||
const file = fileInput.files[0];
|
||||
const chunkSize = 10 * 1024 * 1024; // 10 MB
|
||||
const totalChunks = Math.ceil(file.size / chunkSize);
|
||||
|
||||
for (let chunkIndex = 0; chunkIndex < totalChunks; chunkIndex++) {
|
||||
const start = chunkIndex * chunkSize;
|
||||
const end = Math.min(start + chunkSize, file.size);
|
||||
const chunk = file.slice(start, end);
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('chunk', chunk);
|
||||
formData.append('filename', file.name);
|
||||
formData.append('chunkIndex', chunkIndex);
|
||||
formData.append('totalChunks', totalChunks);
|
||||
|
||||
const response = await fetch('/upload', {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
console.error('Failed to upload chunk', chunkIndex);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
console.log('File uploaded successfully');
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,166 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type Admin struct {
|
||||
name string
|
||||
}
|
||||
|
||||
type UploadState int
|
||||
|
||||
const (
|
||||
inactive UploadState = iota
|
||||
active
|
||||
completed
|
||||
)
|
||||
|
||||
type UploadContext struct {
|
||||
maxSize int64
|
||||
created time.Time
|
||||
state UploadState
|
||||
finalName string
|
||||
}
|
||||
|
||||
type UploadDatabase struct {
|
||||
data map[uuid.UUID]UploadContext
|
||||
mtx sync.Mutex
|
||||
}
|
||||
|
||||
var db UploadDatabase
|
||||
|
||||
func (d *UploadDatabase) commit(size int64, finalName string, lifefile time.Duration) uuid.UUID {
|
||||
id := uuid.New()
|
||||
d.mtx.Lock()
|
||||
defer d.mtx.Unlock()
|
||||
|
||||
_, found := d.data[id]
|
||||
|
||||
if found {
|
||||
return uuid.Max
|
||||
}
|
||||
|
||||
d.data[id] = UploadContext{
|
||||
created: time.Now(),
|
||||
finalName: finalName,
|
||||
maxSize: size,
|
||||
state: inactive,
|
||||
}
|
||||
|
||||
return id
|
||||
}
|
||||
|
||||
func (d *UploadDatabase) activate(id uuid.UUID) *UploadContext {
|
||||
d.mtx.Lock()
|
||||
defer d.mtx.Unlock()
|
||||
|
||||
// i, found := d.data[id]
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *UploadDatabase) deactivate(id uuid.UUID) {
|
||||
|
||||
}
|
||||
|
||||
func initialize() {
|
||||
db.data = make(map[uuid.UUID]UploadContext)
|
||||
}
|
||||
|
||||
func adminHandler(w http.ResponseWriter, r *http.Request) {
|
||||
http.ServeFile(w, r, "./html/admin.html")
|
||||
}
|
||||
|
||||
func generateHandler(w http.ResponseWriter, r *http.Request) {
|
||||
var maxSizeBytes int64
|
||||
var linkLifetime int64
|
||||
var id uuid.UUID
|
||||
var uploadLink string
|
||||
|
||||
if r.Method != "POST" {
|
||||
w.WriteHeader(http.StatusMethodNotAllowed)
|
||||
}
|
||||
|
||||
var linkSettings struct {
|
||||
Lifetime string `json:"lifetime"`
|
||||
MaxSize string `json:"maxSize"`
|
||||
SizeUnit string `json:"sizeUnit"`
|
||||
}
|
||||
err := json.NewDecoder(r.Body).Decode(&linkSettings)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("Invalid input: %v", err), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
linkLifetime, err = strconv.ParseInt(linkSettings.Lifetime, 10, 64)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("Invalid input: %v", err), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
maxSizeBytes, err = strconv.ParseInt(linkSettings.MaxSize, 10, 64)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("Invalid input: %v", err), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if linkSettings.SizeUnit == "GB" {
|
||||
maxSizeBytes *= 1024 * 1024 * 1024
|
||||
} else if linkSettings.SizeUnit == "MB" {
|
||||
maxSizeBytes *= 1024 * 1024
|
||||
} else {
|
||||
http.Error(w, fmt.Sprintf("Invalid input: %v", err), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
id = db.commit(int64(maxSizeBytes), "untitled"+time.Now().String(), time.Duration(linkLifetime))
|
||||
if id == uuid.Max {
|
||||
http.Error(w, "Commit failed", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
uploadLink = fmt.Sprintf("https://localhost:8080/upload?key=%s", id)
|
||||
|
||||
response := map[string]string{"uploadLink": uploadLink}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
if err := json.NewEncoder(w).Encode(response); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func uploadHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
}
|
||||
|
||||
func fileHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
}
|
||||
|
||||
func main() {
|
||||
initialize()
|
||||
|
||||
os.MkdirAll("uploads", os.ModePerm)
|
||||
|
||||
http.HandleFunc("/admin", adminHandler)
|
||||
http.HandleFunc("/generate", generateHandler)
|
||||
http.HandleFunc("/upload", uploadHandler)
|
||||
http.HandleFunc("/file", fileHandler)
|
||||
|
||||
// http.Handle("/", http.FileServer(http.Dir(".")))
|
||||
|
||||
// Start the server
|
||||
fmt.Println("Starting server on :8080")
|
||||
err := http.ListenAndServe(":8080", nil)
|
||||
if err != nil {
|
||||
fmt.Printf("Error starting server: %v", err)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue