modified: serv_nginx/api_bb/internal/handlers/avatar.go

modified:   serv_nginx/api_bb/internal/handlers/handlers.go
	modified:   serv_nginx/api_bb/internal/handlers/user.go
	modified:   serv_nginx/api_bb/internal/routes/routes.go
	modified:   serv_nginx/api_bb/internal/service/avatar_service.go
	modified:   serv_nginx/nginx/nginx-ssl.conf
try to serve file name throught path
This commit is contained in:
2025-10-14 12:41:16 +05:00
parent 46549f5d22
commit bbf470617b
6 changed files with 226 additions and 30 deletions
@@ -19,6 +19,8 @@ type AvatarService interface {
UploadAvatar(userID uint, file multipart.File, header *multipart.FileHeader) (string, error)
DeleteAvatar(userID uint) error
GetAvatarPath(userID uint) (string, error)
GetAvatarFile(filename string) ([]byte, string, error) // НОВЫЙ МЕТОД
ServeAvatarFile(w io.Writer, filename string) (string, error)
}
type avatarService struct {
@@ -111,3 +113,103 @@ func (s *avatarService) GetAvatarPath(userID uint) (string, error) {
}
return user.Avatar, nil
}
func (s *avatarService) GetAvatarFile(filename string) ([]byte, string, error) {
// Валидация имени файла
if filename == "" || strings.Contains(filename, "..") || strings.Contains(filename, "/") {
return nil, "", fmt.Errorf("invalid filename")
}
// Проверяем допустимые расширения
allowedExts := map[string]string{
".png": "image/png",
".jpg": "image/jpeg",
".jpeg": "image/jpeg",
".gif": "image/gif",
".webp": "image/webp",
}
fileExt := strings.ToLower(filepath.Ext(filename))
contentType, exists := allowedExts[fileExt]
if !exists {
return nil, "", fmt.Errorf("unsupported file format")
}
// Формируем путь к файлу
filePath := filepath.Join("./uploads/avatars", filename)
// Проверяем существование файла
fileInfo, err := os.Stat(filePath)
if err != nil {
if os.IsNotExist(err) {
return nil, "", fmt.Errorf("avatar file not found")
}
return nil, "", fmt.Errorf("failed to access file: %v", err)
}
// Проверяем размер файла (максимум 10MB)
if fileInfo.Size() > 10*1024*1024 {
return nil, "", fmt.Errorf("file too large")
}
// Читаем файл
fileData, err := os.ReadFile(filePath)
if err != nil {
return nil, "", fmt.Errorf("failed to read file: %v", err)
}
return fileData, contentType, nil
}
func (s *avatarService) ServeAvatarFile(w io.Writer, filename string) (string, error) {
// Валидация имени файла
if filename == "" || strings.Contains(filename, "..") || strings.Contains(filename, "/") {
return "", fmt.Errorf("invalid filename")
}
// Проверяем допустимые расширения
allowedExts := map[string]string{
".png": "image/png",
".jpg": "image/jpeg",
".jpeg": "image/jpeg",
".gif": "image/gif",
".webp": "image/webp",
}
fileExt := strings.ToLower(filepath.Ext(filename))
contentType, exists := allowedExts[fileExt]
if !exists {
return "", fmt.Errorf("unsupported file format")
}
// Формируем путь к файлу
filePath := filepath.Join("./uploads/avatars", filename)
// Проверяем существование файла
fileInfo, err := os.Stat(filePath)
if err != nil {
if os.IsNotExist(err) {
return "", fmt.Errorf("avatar file not found")
}
return "", fmt.Errorf("failed to access file: %v", err)
}
// Проверяем размер файла
if fileInfo.Size() > 10*1024*1024 {
return "", fmt.Errorf("file too large")
}
// Открываем и копируем файл
file, err := os.Open(filePath)
if err != nil {
return "", fmt.Errorf("failed to open file: %v", err)
}
defer file.Close()
_, err = io.Copy(w, file)
if err != nil {
return "", fmt.Errorf("failed to serve file: %v", err)
}
return contentType, nil
}