2025-04-21 16:04:12 +05:00

238 lines
6.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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)
}
*/