1
Fork 0
photoview/api/routes/downloads.go

110 lines
3.2 KiB
Go
Raw Normal View History

2021-09-26 00:21:02 +02:00
package routes
import (
"archive/zip"
"fmt"
"io"
"log"
"net/http"
"os"
2021-09-26 12:02:53 +02:00
"strings"
2021-09-26 00:21:02 +02:00
"github.com/gorilla/mux"
"github.com/photoview/photoview/api/database/drivers"
2021-09-26 00:21:02 +02:00
"github.com/photoview/photoview/api/graphql/models"
"gorm.io/gorm"
)
func RegisterDownloadRoutes(db *gorm.DB, router *mux.Router) {
router.HandleFunc("/album/{album_id}/{media_purpose}", func(w http.ResponseWriter, r *http.Request) {
albumID := mux.Vars(r)["album_id"]
mediaPurpose := mux.Vars(r)["media_purpose"]
2021-09-26 12:02:53 +02:00
mediaPurposeList := strings.SplitN(mediaPurpose, ",", 10)
2021-09-26 00:21:02 +02:00
var album models.Album
if err := db.Find(&album, albumID).Error; err != nil {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte("404"))
return
}
2021-09-26 12:02:53 +02:00
if success, response, status, err := authenticateAlbum(&album, db, r); !success {
if err != nil {
log.Printf("WARN: error authenticating album for download: %v\n", err)
}
w.WriteHeader(status)
w.Write([]byte(response))
return
}
var mediaWhereQuery string
if drivers.POSTGRES.MatchDatabase(db) {
mediaWhereQuery = "\"Media\".album_id = ?"
} else {
mediaWhereQuery = "Media.album_id = ?"
}
2021-09-26 00:21:02 +02:00
var mediaURLs []*models.MediaURL
if err := db.Joins("Media").Where(mediaWhereQuery, album.ID).Where("media_urls.purpose IN (?)", mediaPurposeList).Find(&mediaURLs).Error; err != nil {
2021-09-26 00:21:02 +02:00
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte("internal server error"))
return
}
2021-09-26 12:02:53 +02:00
if len(mediaURLs) == 0 {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte("no media found"))
return
}
2021-09-26 00:21:02 +02:00
w.Header().Set("Content-Type", "application/zip")
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s.zip\"", album.Title))
zipWriter := zip.NewWriter(w)
for _, media := range mediaURLs {
2021-09-26 13:10:37 +02:00
zipFile, err := zipWriter.Create(fmt.Sprintf("%s/%s", album.Title, media.MediaName))
2021-09-26 00:21:02 +02:00
if err != nil {
log.Printf("ERROR: Failed to create a file in zip, when downloading album (%d): %v\n", album.ID, err)
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte("internal server error"))
return
}
filePath, err := media.CachedPath()
if err != nil {
log.Printf("ERROR: Failed to get mediaURL cache path, when downloading album (%d): %v\n", album.ID, err)
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte("internal server error"))
return
}
fileData, err := os.Open(filePath)
if err != nil {
log.Printf("ERROR: Failed to open file to include in zip, when downloading album (%d): %v\n", album.ID, err)
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte("internal server error"))
return
}
_, err = io.Copy(zipFile, fileData)
if err != nil {
log.Printf("ERROR: Failed to copy file data, when downloading album (%d): %v\n", album.ID, err)
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte("internal server error"))
return
}
if err := fileData.Close(); err != nil {
log.Printf("ERROR: Failed to close file, when downloading album (%d): %v\n", album.ID, err)
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte("internal server error"))
return
}
}
// close the zip Writer to flush the contents to the ResponseWriter
zipWriter.Close()
})
}