package handlersHTTP import ( "encoding/json" "fmt" "git.insit.tech/psa/rtsp_reader-writer/reader/internal/config" "git.insit.tech/psa/rtsp_reader-writer/reader/internal/processor" "git.insit.tech/psa/rtsp_reader-writer/reader/internal/web/handlers" "git.insit.tech/psa/rtsp_reader-writer/writer/pkg/storage" "github.com/gofiber/fiber/v2" "log" "net/http" "os" ) // Download processes Download request. func Download(w http.ResponseWriter, r *http.Request) { log.Printf("new download request: %+v\n", r) downloadRequest := handlers.VideoRequest{} err := json.NewDecoder(r.Body).Decode(&downloadRequest) if err != nil { log.Printf("json decode error: %v\n", err) w.WriteHeader(http.StatusBadRequest) return } pathFileNameRes, err := processor.Process(downloadRequest.Date, downloadRequest.StartTime, downloadRequest.EndTime) if err != nil { log.Printf("process error: %v\n", err) w.WriteHeader(http.StatusBadRequest) return } w.Header().Set("Content-Type", "video/mp4") // Разрешаем частичную загрузку (поддержка перемотки) w.Header().Set("Accept-Ranges", "bytes") http.ServeFile(w, r, pathFileNameRes) } // HLS processes Download request. func HLS(w http.ResponseWriter, r *http.Request) { log.Printf("new hls request: %+v\n", r) path := "/home/psa/GoRepository/data/1280x720/" w.Header().Set("Access-Control-Allow-Origin", "*") http.StripPrefix("/hls", http.FileServer(http.Dir(path))).ServeHTTP(w, r) } // ConfigVodsHandler returns configuration of the requested VOD location. // // This method allows to get a single VOD location. func ConfigVodsHandler(c *fiber.Ctx) error { // Read camera id. id := c.Params("id") // Get resolutions. resolutions, err := storage.GetResolutions(id) if err != nil { return c.SendStatus(fiber.StatusBadRequest) } // Calculate response fields. // Create path to first resolution. resDir := fmt.Sprintf("%s/%s/%s", config.DirData, id, resolutions[0]) // Read directory. entries, err := os.ReadDir(resDir) if err != nil { return c.SendStatus(fiber.StatusInternalServerError) } // Check if a folder has files that was not created or modified for last 5 minutes. disabled, err := handlers.Inactive5Minutes(entries) if err != nil { return c.SendStatus(fiber.StatusInternalServerError) } // Calculate the difference between first existing rec file and the last one in milliseconds. segmentDuration, err := handlers.RecDurationMilliseconds(entries) if err != nil { return c.SendStatus(fiber.StatusInternalServerError) } // Prepare the Response. VodsRes := handlers.ConfigVodsResponse{ Prefix: id, AutoMbr: false, // Always false. Temporary. Disabled: disabled, SegmentDuration: segmentDuration, AddAudioOnly: false, // Always false. Temporary. Provider: "Insit", } // Write header and code response. return c.JSON(VodsRes) } // DelVodsHandler delete archive of the requested VOD location. // // This method delete a single VOD location by its prefix. func DelVodsHandler(c *fiber.Ctx) error { // Read camera id. id := c.Params("id") err := os.Remove(fmt.Sprintf("%s/%s", config.DirData, id)) if err != nil { return c.SendStatus(fiber.StatusBadRequest) } return c.SendStatus(fiber.StatusNoContent) } // ListFilesVodsHandler returns the list of all files and folders in archive for a specific VOD location. // // This method allows to get the list of all files and folders for a specific VOD location. func ListFilesVodsHandler(c *fiber.Ctx) error { // Read camera id. id := c.Params("id") // Create map for response. files := make(map[string][]string) // Get resolutions. resolutions, err := storage.GetResolutions(id) if err != nil { return c.SendStatus(fiber.StatusBadRequest) } for _, resolution := range resolutions { // Create path to the resolutions. resDir := fmt.Sprintf("%s/%s/%s", config.DirData, id, resolution) // Read directory. entries, err := os.ReadDir(resDir) if err != nil { return c.SendStatus(fiber.StatusInternalServerError) } // Create slice for files in folders. filesInFolder := make([]string, 0) // Add all files to the slice with files. for _, entry := range entries { filesInFolder = append(filesInFolder, entry.Name()) } // Add resolution and all files to the response map. files[resolution] = filesInFolder } // Prepare the Response. vodsRes := handlers.ListVodsResponse{ EstimatedCount: len(files), Files: files, } // Write header and code response. return c.JSON(vodsRes) } // SingleVodsHandler returns a specific file in archive for a specific resolution and VOD location. // // This method allows to get a single VOD file. func SingleVodsHandler(c *fiber.Ctx) error { // Read camera id, res, filename. id := c.Params("id") res := c.Params("res") file := c.Params("file") // Calculate file size in bytes. FileBytes, err := storage.FileBytes(id, res, file) if err != nil { return c.SendStatus(fiber.StatusBadRequest) } dur, tracks, err := storage.GetDurAndTracks(id, res, file) if err != nil { return c.SendStatus(fiber.StatusInternalServerError) } media := handlers.MediaSingleVodsResponse{ Tracks: tracks, Duration: dur, Provider: "Insit", Title: id, } // Prepare the Response. vodsRes := handlers.SingleVodsResponse{ Name: file, Prefix: id, Url: c.OriginalURL(), Folder: res, Bytes: FileBytes, MediaInfo: media, } // Write header and code response. return c.JSON(vodsRes) } // DelSingleVodsHandler deletes a VOD file by its name. // // This method deletes a VOD file by its name. func DelSingleVodsHandler(c *fiber.Ctx) error { // Read camera id, res, filename. id := c.Params("id") res := c.Params("res") file := c.Params("file") if err := os.Remove(fmt.Sprintf("%s/%s/%s/%s", config.DirData, id, res, file)); err != nil { return c.SendStatus(fiber.StatusNotFound) } return c.SendStatus(fiber.StatusNoContent) } /* // FileHandler обработчик для работы с файлами func FileHandler(c *fiber.Ctx) error { // Если запрос содержит session_id - получаем файл sessionData := c.Locals(ContextKeySession).(*SessionData) // Логика получения файла fileContent, err := getFileContent(sessionData.FileName) if err != nil { return c.Status(fiber.StatusNotFound).SendString("File not found") } return c.Send(fileContent) } */