Skip to content

Commit 87dea2c

Browse files
Add bucket storage for attachments
1 parent 1538a9e commit 87dea2c

File tree

4 files changed

+82
-40
lines changed

4 files changed

+82
-40
lines changed

models/attachment.go

Lines changed: 73 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
package models
66

77
import (
8+
"context"
89
"fmt"
910
"io"
10-
"os"
1111
"path"
1212

1313
"code.gitea.io/gitea/modules/setting"
@@ -16,6 +16,7 @@ import (
1616

1717
"github.com/go-xorm/xorm"
1818
gouuid "github.com/satori/go.uuid"
19+
"gocloud.dev/blob"
1920
)
2021

2122
// Attachment represent a attachment of issue/comment/release.
@@ -71,33 +72,41 @@ func (a *Attachment) DownloadURL() string {
7172
return fmt.Sprintf("%sattachments/%s", setting.AppURL, a.UUID)
7273
}
7374

74-
// NewAttachment creates a new attachment object.
75-
func NewAttachment(attach *Attachment, buf []byte, file io.Reader) (_ *Attachment, err error) {
76-
attach.UUID = gouuid.NewV4().String()
77-
78-
localPath := attach.LocalPath()
79-
if err = os.MkdirAll(path.Dir(localPath), os.ModePerm); err != nil {
80-
return nil, fmt.Errorf("MkdirAll: %v", err)
75+
// uploadAttachmentToBucket uploads attachments to bucket
76+
func (attach *Attachment) UploadAttachmentToBucket(buf []byte, file io.Reader) (*Attachment, error) {
77+
ctx := context.Background()
78+
bucket, err := blob.OpenBucket(ctx, setting.FileStorage.Bucket)
79+
if err != nil {
80+
return nil, fmt.Errorf("Failed to setup bucket: %v", err)
8181
}
82+
bucket = blob.PrefixedBucket(bucket, "data/attachments/")
8283

83-
fw, err := os.Create(localPath)
84+
bucketWriter, err := bucket.NewWriter(ctx, attach.LocalPath(), nil)
8485
if err != nil {
85-
return nil, fmt.Errorf("Create: %v", err)
86+
return nil, fmt.Errorf("Failed to obtain writer: %v", err)
8687
}
87-
defer fw.Close()
88+
var fileSize int64
89+
if _, err = bucketWriter.Write(buf); err != nil {
90+
return nil, fmt.Errorf("error occurred while writing: %v", err)
91+
} else if fileSize, err = io.Copy(bucketWriter, file); err != nil {
92+
return nil, fmt.Errorf("error occurred while copying: %v", err)
93+
}
94+
attach.Size = fileSize
8895

89-
if _, err = fw.Write(buf); err != nil {
90-
return nil, fmt.Errorf("Write: %v", err)
91-
} else if _, err = io.Copy(fw, file); err != nil {
92-
return nil, fmt.Errorf("Copy: %v", err)
96+
if err = bucketWriter.Close(); err != nil {
97+
return nil, fmt.Errorf("Failed to close: %v", err)
9398
}
99+
return attach, nil
100+
}
101+
102+
// NewAttachment creates a new attachment object.
103+
func NewAttachment(attach *Attachment, buf []byte, file io.Reader) (_ *Attachment, err error) {
104+
attach.UUID = gouuid.NewV4().String()
94105

95-
// Update file size
96-
var fi os.FileInfo
97-
if fi, err = fw.Stat(); err != nil {
98-
return nil, fmt.Errorf("file size: %v", err)
106+
attach, err = attach.UploadAttachmentToBucket(buf, file)
107+
if err != nil {
108+
return nil, err
99109
}
100-
attach.Size = fi.Size()
101110

102111
if _, err := x.Insert(attach); err != nil {
103112
return nil, err
@@ -185,6 +194,49 @@ func getAttachmentByReleaseIDFileName(e Engine, releaseID int64, fileName string
185194
return attach, nil
186195
}
187196

197+
// GetAttachmentReader provides attachment reader from bucket
198+
func (attach *Attachment) GetAttachmentReader() (io.ReadCloser, error) {
199+
ctx := context.Background()
200+
bucket, err := blob.OpenBucket(ctx, setting.FileStorage.Bucket)
201+
if err != nil {
202+
return nil, fmt.Errorf("Failed to setup bucket %v", err)
203+
}
204+
bucket = blob.PrefixedBucket(bucket, "data/attachments/")
205+
206+
exist, err := bucket.Exists(ctx, attach.LocalPath())
207+
if err != nil {
208+
return nil, err
209+
} else if !exist {
210+
return nil, fmt.Errorf("Attachment not found")
211+
}
212+
213+
reader, err := bucket.NewReader(ctx, attach.LocalPath(), nil)
214+
if err != nil {
215+
return nil, err
216+
}
217+
218+
return reader, nil
219+
}
220+
221+
// deleteAttachmentFromBucket deletes attachments from bucket
222+
func (attach *Attachment) deleteAttachmentFromBucket() error {
223+
ctx := context.Background()
224+
bucket, err := blob.OpenBucket(ctx, setting.FileStorage.Bucket)
225+
if err != nil {
226+
return fmt.Errorf("Failed to setup bucket: %v", err)
227+
}
228+
bucket = blob.PrefixedBucket(bucket, "data/attachments/")
229+
230+
exist, err := bucket.Exists(ctx, attach.LocalPath())
231+
if err != nil {
232+
return err
233+
} else if !exist {
234+
return fmt.Errorf("repo avatar not found")
235+
}
236+
237+
return bucket.Delete(ctx, attach.LocalPath())
238+
}
239+
188240
// DeleteAttachment deletes the given attachment and optionally the associated file.
189241
func DeleteAttachment(a *Attachment, remove bool) error {
190242
_, err := DeleteAttachments([]*Attachment{a}, remove)
@@ -209,7 +261,7 @@ func DeleteAttachments(attachments []*Attachment, remove bool) (int, error) {
209261

210262
if remove {
211263
for i, a := range attachments {
212-
if err := os.Remove(a.LocalPath()); err != nil {
264+
if err := a.deleteAttachmentFromBucket(); err != nil {
213265
return i, err
214266
}
215267
}

modules/migrations/gitea.go

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import (
1010
"io"
1111
"net/http"
1212
"os"
13-
"path"
1413
"path/filepath"
1514
"strings"
1615
"sync"
@@ -204,22 +203,17 @@ func (g *GiteaLocalUploader) CreateReleases(releases ...*base.Release) error {
204203
}
205204
defer resp.Body.Close()
206205

207-
localPath := attach.LocalPath()
208-
if err = os.MkdirAll(path.Dir(localPath), os.ModePerm); err != nil {
209-
return fmt.Errorf("MkdirAll: %v", err)
206+
buf := make([]byte, 1024)
207+
n, _ := resp.Body.Read(buf)
208+
if n > 0 {
209+
buf = buf[:n]
210210
}
211-
212-
fw, err := os.Create(localPath)
211+
attachment, err := attach.UploadAttachmentToBucket(buf, resp.Body)
213212
if err != nil {
214-
return fmt.Errorf("Create: %v", err)
215-
}
216-
defer fw.Close()
217-
218-
if _, err := io.Copy(fw, resp.Body); err != nil {
219213
return err
220214
}
221215

222-
rel.Attachments = append(rel.Attachments, &attach)
216+
rel.Attachments = append(rel.Attachments, attachment)
223217
}
224218

225219
rels = append(rels, &rel)

modules/setting/setting.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -782,9 +782,6 @@ func NewContext() {
782782

783783
sec = Cfg.Section("attachment")
784784
AttachmentPath = sec.Key("PATH").MustString(path.Join(AppDataPath, "attachments"))
785-
if !filepath.IsAbs(AttachmentPath) {
786-
AttachmentPath = path.Join(AppWorkPath, AttachmentPath)
787-
}
788785
AttachmentAllowedTypes = strings.Replace(sec.Key("ALLOWED_TYPES").MustString("image/jpeg,image/png,application/zip,application/gzip"), "|", ",", -1)
789786
AttachmentMaxSize = sec.Key("MAX_SIZE").MustInt64(4)
790787
AttachmentMaxFiles = sec.Key("MAX_FILES").MustInt(5)

routers/routes/routes.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import (
88
"bytes"
99
"encoding/gob"
1010
"net/http"
11-
"os"
1211
"path"
1312
"text/template"
1413
"time"
@@ -489,19 +488,19 @@ func RegisterRoutes(m *macaron.Macaron) {
489488
return
490489
}
491490

492-
fr, err := os.Open(attach.LocalPath())
491+
reader, err := attach.GetAttachmentReader()
493492
if err != nil {
494493
ctx.ServerError("Open", err)
495494
return
496495
}
497-
defer fr.Close()
496+
defer reader.Close()
498497

499498
if err := attach.IncreaseDownloadCount(); err != nil {
500499
ctx.ServerError("Update", err)
501500
return
502501
}
503502

504-
if err = repo.ServeData(ctx, attach.Name, fr); err != nil {
503+
if err = repo.ServeData(ctx, attach.Name, reader); err != nil {
505504
ctx.ServerError("ServeData", err)
506505
return
507506
}

0 commit comments

Comments
 (0)