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"
|
2021-11-06 15:41:25 +01:00
|
|
|
"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
|
|
|
|
}
|
|
|
|
|
2021-09-26 15:15:31 +02:00
|
|
|
var mediaWhereQuery string
|
2021-11-06 15:41:25 +01:00
|
|
|
if drivers.POSTGRES.MatchDatabase(db) {
|
2021-09-26 15:15:31 +02:00
|
|
|
mediaWhereQuery = "\"Media\".album_id = ?"
|
|
|
|
} else {
|
|
|
|
mediaWhereQuery = "Media.album_id = ?"
|
|
|
|
}
|
|
|
|
|
2021-09-26 00:21:02 +02:00
|
|
|
var mediaURLs []*models.MediaURL
|
2021-09-26 15:15:31 +02:00
|
|
|
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()
|
|
|
|
})
|
|
|
|
}
|