GraphQL API and utilities for the rpdata project
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

93 lines
2.4 KiB

  1. package space
  2. import (
  3. "context"
  4. "errors"
  5. "fmt"
  6. "git.aiterp.net/rpdata/api/internal/config"
  7. "io"
  8. minio "github.com/minio/minio-go"
  9. )
  10. type Client struct {
  11. bucket string
  12. urlRoot string
  13. spaceRoot string
  14. maxSize int64
  15. s3 *minio.Client
  16. }
  17. func (client *Client) MaxSize() int64 {
  18. return client.maxSize
  19. }
  20. // UploadFile uploads the file to the space. This does not do any checks on it, so the endpoints should
  21. // ensure that's all okay.
  22. func (client *Client) UploadFile(ctx context.Context, folder string, name string, mimeType string, reader io.Reader, size int64) (string, error) {
  23. path := folder + "/" + name
  24. if size > client.maxSize {
  25. return "", errors.New("file is too big")
  26. }
  27. _, err := client.s3.PutObjectWithContext(ctx, client.bucket, client.spaceRoot+"/"+path, reader, size, minio.PutObjectOptions{
  28. ContentType: mimeType,
  29. UserMetadata: map[string]string{
  30. "x-amz-acl": "public-read",
  31. },
  32. })
  33. if err != nil {
  34. return "", err
  35. }
  36. _, err = client.s3.StatObject(client.bucket, client.spaceRoot+"/"+path, minio.StatObjectOptions{})
  37. if err != nil {
  38. return "", err
  39. }
  40. return path, nil
  41. }
  42. // RemoveFile removes a file from the space
  43. func (client *Client) RemoveFile(folder string, name string) error {
  44. path := folder + "/" + name
  45. return client.s3.RemoveObject(client.bucket, client.spaceRoot+"/"+path)
  46. }
  47. // DownloadFile opens a file for download, using the same path format as the UploadFile function. Remember to Close it!
  48. // The returned stream also has `ReaderAt` and `Seeker`, but those are impl. details.
  49. func (client *Client) DownloadFile(ctx context.Context, path string) (io.ReadCloser, error) {
  50. return client.s3.GetObjectWithContext(ctx, client.bucket, client.spaceRoot+"/"+path, minio.GetObjectOptions{})
  51. }
  52. // URLFromPath gets the URL from the path returned by UploadFile
  53. func (client *Client) URLFromPath(path string) string {
  54. return client.urlRoot + path
  55. }
  56. // Connect connects to a S3 space.
  57. func Connect(cfg config.Space) (*Client, error) {
  58. client, err := minio.New(cfg.Host, cfg.AccessKey, cfg.SecretKey, true)
  59. if err != nil {
  60. return nil, err
  61. }
  62. exists, err := client.BucketExists(cfg.Bucket)
  63. if err != nil {
  64. return nil, err
  65. }
  66. if !exists {
  67. return nil, errors.New("bucket not found")
  68. }
  69. return &Client{
  70. bucket: cfg.Bucket,
  71. urlRoot: fmt.Sprintf("https://%s.%s/%s/", cfg.Bucket, cfg.Host, cfg.Root),
  72. spaceRoot: cfg.Root,
  73. maxSize: cfg.MaxSize,
  74. s3: client,
  75. }, nil
  76. }