ultisuite-backend/internal/nextcloud/preview.go
2026-06-04 00:12:11 +02:00

97 lines
2.3 KiB
Go

package nextcloud
import (
"context"
"encoding/xml"
"fmt"
"io"
"net/http"
"strconv"
"strings"
)
func (c *Client) FileID(ctx context.Context, userID, filePath string) (int64, error) {
filePath = NormalizeClientFilePath(userID, filePath)
davPath := c.WebDAVPath(userID, filePath)
body := `<?xml version="1.0" encoding="UTF-8"?>
<d:propfind xmlns:d="DAV:" xmlns:oc="http://owncloud.org/ns">
<d:prop>
<oc:fileid/>
</d:prop>
</d:propfind>`
resp, err := c.DoAsUser(ctx, "PROPFIND", davPath, strings.NewReader(body), userID, map[string]string{
"Depth": "0",
"Content-Type": "application/xml",
})
if err != nil {
return 0, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusMultiStatus && resp.StatusCode != http.StatusOK {
return 0, &HTTPStatusError{Operation: "propfind fileid", StatusCode: resp.StatusCode}
}
var ms struct {
Responses []struct {
Propstat struct {
Prop struct {
FileID string `xml:"http://owncloud.org/ns fileid"`
} `xml:"prop"`
} `xml:"propstat"`
} `xml:"response"`
}
if err := xml.NewDecoder(resp.Body).Decode(&ms); err != nil {
return 0, err
}
if len(ms.Responses) == 0 {
return 0, fmt.Errorf("fileid propfind: empty response")
}
raw := strings.TrimSpace(ms.Responses[0].Propstat.Prop.FileID)
if raw == "" {
return 0, fmt.Errorf("fileid propfind: missing fileid")
}
// Nextcloud may return "00001234" — keep numeric part.
id, err := strconv.ParseInt(raw, 10, 64)
if err != nil {
return 0, fmt.Errorf("fileid propfind: invalid fileid %q", raw)
}
return id, nil
}
func (c *Client) Preview(ctx context.Context, userID string, fileID int64, width, height int) (io.ReadCloser, string, error) {
if width <= 0 {
width = 400
}
if height <= 0 {
height = 300
}
if width > 2048 {
width = 2048
}
if height > 2048 {
height = 2048
}
path := fmt.Sprintf(
"/index.php/core/preview?fileId=%d&x=%d&y=%d&a=1&mode=cover&mimeFallback=true",
fileID, width, height,
)
resp, err := c.DoAsUser(ctx, "GET", path, nil, userID, nil)
if err != nil {
return nil, "", err
}
if resp.StatusCode != http.StatusOK {
resp.Body.Close()
return nil, "", &HTTPStatusError{Operation: "preview", StatusCode: resp.StatusCode}
}
contentType := resp.Header.Get("Content-Type")
if contentType == "" {
contentType = "image/jpeg"
}
return resp.Body, contentType, nil
}