1 parent
fca32c2233
commit
7f0e5b7b10
8 files changed
+21
-105
No files matched your search
+4
-20
@@ -14,7 +14,6 @@ import (
|
||||
"up/utils"
|
||||
)
|
||||
|
||||
// Глобальное состояние загрузки (аналог g_upload в C)
|
||||
type UploadState struct {
|
||||
mu sync.RWMutex
|
||||
Type string
|
||||
@@ -25,7 +24,7 @@ type UploadState struct {
|
||||
|
||||
var uploadState UploadState
|
||||
|
||||
// handleUpload обрабатывает POST /api/upload
|
||||
// POST /api/upload
|
||||
func HandleUpload(w http.ResponseWriter, r *http.Request) {
|
||||
uboot_max_size_int, err := strconv.Atoi(os.Getenv("UBOOT_MAX_SIZE"))
|
||||
if err != nil {
|
||||
@@ -40,15 +39,13 @@ func HandleUpload(w http.ResponseWriter, r *http.Request) {
|
||||
UBOOT_MAX_SIZE := uboot_max_size_int * 1024 * 1024
|
||||
MAX_FILE_SIZE := max_file_size_int * 1024 * 1024
|
||||
MOUNT_POINT := os.Getenv("MOUNT_POINT")
|
||||
// Ограничиваем размер запроса (максимум UBOOT_MAX_SIZE + запас)
|
||||
r.Body = http.MaxBytesReader(w, r.Body, int64(MAX_FILE_SIZE)+1024)
|
||||
if err := r.ParseMultipartForm(32 << 20); err != nil { // 32 MB в памяти
|
||||
http.Error(w, `{"error":"Failed to parse multipart form"}`, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
defer r.MultipartForm.RemoveAll() // очищаем временные файлы
|
||||
defer r.MultipartForm.RemoveAll()
|
||||
|
||||
// Получаем поле "type"
|
||||
typeVals := r.MultipartForm.Value["type"]
|
||||
if len(typeVals) == 0 {
|
||||
http.Error(w, `{"error":"Missing type field"}`, http.StatusBadRequest)
|
||||
@@ -56,7 +53,6 @@ func HandleUpload(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
typ := typeVals[0]
|
||||
|
||||
// Получаем файл из поля "file"
|
||||
files := r.MultipartForm.File["file"]
|
||||
if len(files) == 0 {
|
||||
http.Error(w, `{"error":"Missing file field"}`, http.StatusBadRequest)
|
||||
@@ -64,7 +60,6 @@ func HandleUpload(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
fileHeader := files[0]
|
||||
|
||||
// Проверка размера файла
|
||||
maxSize := int64(MAX_FILE_SIZE)
|
||||
if typ == "uboot_bin" {
|
||||
maxSize = int64(UBOOT_MAX_SIZE)
|
||||
@@ -74,7 +69,6 @@ func HandleUpload(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
// Открываем загруженный файл
|
||||
srcFile, err := fileHeader.Open()
|
||||
if err != nil {
|
||||
http.Error(w, `{"error":"Failed to open uploaded file"}`, http.StatusInternalServerError)
|
||||
@@ -82,13 +76,11 @@ func HandleUpload(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
defer srcFile.Close()
|
||||
|
||||
// Монтируем устройство
|
||||
if utils.MountDevice() < 0 {
|
||||
http.Error(w, `{"error":"Failed to mount device"}`, http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Определяем имя файла назначения
|
||||
filename := utils.GetTargetFilename(typ)
|
||||
if filename == "" {
|
||||
http.Error(w, `{"error":"Invalid upload type"}`, http.StatusBadRequest)
|
||||
@@ -96,7 +88,6 @@ func HandleUpload(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
destPath := filepath.Join(MOUNT_POINT, filename)
|
||||
|
||||
// Обновляем состояние загрузки
|
||||
uploadState.mu.Lock()
|
||||
uploadState.Type = typ
|
||||
uploadState.Received = 0
|
||||
@@ -106,7 +97,6 @@ func HandleUpload(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
fmt.Printf("Upload: %s (%d bytes) -> %s\n", typ, fileHeader.Size, destPath)
|
||||
|
||||
// Получаем timestamp из query и декодируем
|
||||
timestamp := r.URL.Query().Get("timestamp")
|
||||
if timestamp != "" {
|
||||
decoded, err := url.QueryUnescape(timestamp)
|
||||
@@ -115,7 +105,6 @@ func HandleUpload(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
// Специальная обработка для U-Boot
|
||||
if typ == "uboot_bin" {
|
||||
data, err := io.ReadAll(srcFile)
|
||||
if err != nil {
|
||||
@@ -139,7 +128,6 @@ func HandleUpload(w http.ResponseWriter, r *http.Request) {
|
||||
uploadState.Status = "Complete"
|
||||
uploadState.mu.Unlock()
|
||||
} else {
|
||||
// Обычная запись файла чанками с обновлением прогресса
|
||||
destFile, err := os.Create(destPath)
|
||||
if err != nil {
|
||||
uploadState.mu.Lock()
|
||||
@@ -150,7 +138,7 @@ func HandleUpload(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
defer destFile.Close()
|
||||
|
||||
buf := make([]byte, 65536) // 64 KB чанки
|
||||
buf := make([]byte, 65536) // 64 KB chunks
|
||||
var written int64
|
||||
for {
|
||||
n, err := srcFile.Read(buf)
|
||||
@@ -163,7 +151,6 @@ func HandleUpload(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
written += int64(n)
|
||||
// Обновляем прогресс
|
||||
uploadState.mu.Lock()
|
||||
uploadState.Received = written
|
||||
uploadState.Progress = int(written * 100 / fileHeader.Size)
|
||||
@@ -181,19 +168,17 @@ func HandleUpload(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
destFile.Sync()
|
||||
syscall.Sync() // глобальная синхронизация
|
||||
syscall.Sync()
|
||||
uploadState.mu.Lock()
|
||||
uploadState.Progress = 100
|
||||
uploadState.Status = "Complete"
|
||||
uploadState.mu.Unlock()
|
||||
}
|
||||
|
||||
// Запись файла версии с timestamp
|
||||
if timestamp != "" {
|
||||
versionPath := filepath.Join(MOUNT_POINT, filename+".version")
|
||||
vf, err := os.Create(versionPath)
|
||||
if err == nil {
|
||||
// Форматируем ISO 8601 в читаемый вид (как в C)
|
||||
var readableDate string
|
||||
if len(timestamp) >= 19 {
|
||||
readableDate = timestamp[:10] + " " + timestamp[11:19] // "YYYY-MM-DD HH:MM:SS"
|
||||
@@ -208,7 +193,6 @@ func HandleUpload(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
fmt.Printf("Upload complete: %s\n", destPath)
|
||||
|
||||
// Формируем JSON-ответ
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(map[string]interface{}{
|
||||
|
||||
Reference in new issue
Block a user