diff --git a/pkg/files/downloader.go b/pkg/files/downloader.go new file mode 100644 index 0000000000000000000000000000000000000000..79acfeed5125a755c6908f77a7b66390239cb534 --- /dev/null +++ b/pkg/files/downloader.go @@ -0,0 +1,32 @@ +package files + +import ( + "errors" + "io" + "net/http" +) + +type Downloader interface { + Download(dst io.Writer, file *File) error +} + +type downloader struct{} + +func NewDownloader() Downloader { + return &downloader{} +} + +func (d *downloader) Download(dst io.Writer, file *File) error { + r, err := http.Get(file.URL) + if err != nil { + return err + } + defer r.Body.Close() + + if r.StatusCode != http.StatusOK { + return errors.New("download request failed: " + r.Status) + } + + _, err = io.Copy(dst, r.Body) + return err +} diff --git a/pkg/files/mocks/FileStorage.go b/pkg/files/mocks/FileStorage.go deleted file mode 100644 index 84820da52ed3267935ceebbb7baa24416c4d1be1..0000000000000000000000000000000000000000 --- a/pkg/files/mocks/FileStorage.go +++ /dev/null @@ -1,158 +0,0 @@ -// Code generated by mockery v2.7.4. DO NOT EDIT. - -package mocks - -import ( - context "context" - - file "git.perx.ru/perxis/perxis-go/pkg/files" - mock "github.com/stretchr/testify/mock" -) - -// FileStorage is an autogenerated mock type for the FileStorage type -type FileStorage struct { - mock.Mock -} - -// AbortUpload provides a mock function with given fields: ctx, upload -func (_m *FileStorage) AbortUpload(ctx context.Context, upload *file.MultipartUpload) error { - ret := _m.Called(ctx, upload) - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, *file.MultipartUpload) error); ok { - r0 = rf(ctx, upload) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// CompleteUpload provides a mock function with given fields: ctx, upload -func (_m *FileStorage) CompleteUpload(ctx context.Context, upload *file.MultipartUpload) (*file.MultipartUpload, error) { - ret := _m.Called(ctx, upload) - - var r0 *file.MultipartUpload - if rf, ok := ret.Get(0).(func(context.Context, *file.MultipartUpload) *file.MultipartUpload); ok { - r0 = rf(ctx, upload) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*file.MultipartUpload) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, *file.MultipartUpload) error); ok { - r1 = rf(ctx, upload) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// DeleteFile provides a mock function with given fields: ctx, _a1 -func (_m *FileStorage) DeleteFile(ctx context.Context, _a1 *file.File) error { - ret := _m.Called(ctx, _a1) - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, *file.File) error); ok { - r0 = rf(ctx, _a1) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// GetFile provides a mock function with given fields: ctx, _a1 -func (_m *FileStorage) GetFile(ctx context.Context, _a1 *file.File) (*file.File, error) { - ret := _m.Called(ctx, _a1) - - var r0 *file.File - if rf, ok := ret.Get(0).(func(context.Context, *file.File) *file.File); ok { - r0 = rf(ctx, _a1) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*file.File) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, *file.File) error); ok { - r1 = rf(ctx, _a1) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// MoveUpload provides a mock function with given fields: ctx, src, dst -func (_m *FileStorage) Move(ctx context.Context, src *file.File, dst *file.File) (*file.File, error) { - ret := _m.Called(ctx, src, dst) - - var r0 *file.File - if rf, ok := ret.Get(0).(func(context.Context, *file.File, *file.File) *file.File); ok { - r0 = rf(ctx, src, dst) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*file.File) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, *file.File, *file.File) error); ok { - r1 = rf(ctx, src, dst) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// StartUpload provides a mock function with given fields: ctx, upload -func (_m *FileStorage) StartUpload(ctx context.Context, upload *file.MultipartUpload) (*file.MultipartUpload, error) { - ret := _m.Called(ctx, upload) - - var r0 *file.MultipartUpload - if rf, ok := ret.Get(0).(func(context.Context, *file.MultipartUpload) *file.MultipartUpload); ok { - r0 = rf(ctx, upload) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*file.MultipartUpload) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, *file.MultipartUpload) error); ok { - r1 = rf(ctx, upload) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Upload provides a mock function with given fields: ctx, _a1 -func (_m *FileStorage) Upload(ctx context.Context, _a1 *file.File) (*file.Upload, error) { - ret := _m.Called(ctx, _a1) - - var r0 *file.Upload - if rf, ok := ret.Get(0).(func(context.Context, *file.File) *file.Upload); ok { - r0 = rf(ctx, _a1) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*file.Upload) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, *file.File) error); ok { - r1 = rf(ctx, _a1) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} diff --git a/pkg/files/mocks/Storage.go b/pkg/files/mocks/Storage.go deleted file mode 100644 index 60ad2736bff8fbdfd7cb114ee0a1418053544cee..0000000000000000000000000000000000000000 --- a/pkg/files/mocks/Storage.go +++ /dev/null @@ -1,158 +0,0 @@ -// Code generated by mockery v2.7.4. DO NOT EDIT. - -package mocks - -import ( - context "context" - - files "git.perx.ru/perxis/perxis-go/pkg/files" - mock "github.com/stretchr/testify/mock" -) - -// Storage is an autogenerated mock type for the Storage type -type Storage struct { - mock.Mock -} - -// AbortUpload provides a mock function with given fields: ctx, upload -func (_m *Storage) AbortUpload(ctx context.Context, upload *files.MultipartUpload) error { - ret := _m.Called(ctx, upload) - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, *files.MultipartUpload) error); ok { - r0 = rf(ctx, upload) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// CompleteUpload provides a mock function with given fields: ctx, upload -func (_m *Storage) CompleteUpload(ctx context.Context, upload *files.MultipartUpload) (*files.MultipartUpload, error) { - ret := _m.Called(ctx, upload) - - var r0 *files.MultipartUpload - if rf, ok := ret.Get(0).(func(context.Context, *files.MultipartUpload) *files.MultipartUpload); ok { - r0 = rf(ctx, upload) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*files.MultipartUpload) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, *files.MultipartUpload) error); ok { - r1 = rf(ctx, upload) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// DeleteFile provides a mock function with given fields: ctx, file -func (_m *Storage) DeleteFile(ctx context.Context, file *files.File) error { - ret := _m.Called(ctx, file) - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, *files.File) error); ok { - r0 = rf(ctx, file) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// GetFile provides a mock function with given fields: ctx, file -func (_m *Storage) GetFile(ctx context.Context, file *files.File) (*files.File, error) { - ret := _m.Called(ctx, file) - - var r0 *files.File - if rf, ok := ret.Get(0).(func(context.Context, *files.File) *files.File); ok { - r0 = rf(ctx, file) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*files.File) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, *files.File) error); ok { - r1 = rf(ctx, file) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Move provides a mock function with given fields: ctx, src, dst -func (_m *Storage) Move(ctx context.Context, src *files.File, dst *files.File) (*files.File, error) { - ret := _m.Called(ctx, src, dst) - - var r0 *files.File - if rf, ok := ret.Get(0).(func(context.Context, *files.File, *files.File) *files.File); ok { - r0 = rf(ctx, src, dst) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*files.File) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, *files.File, *files.File) error); ok { - r1 = rf(ctx, src, dst) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// StartUpload provides a mock function with given fields: ctx, upload -func (_m *Storage) StartUpload(ctx context.Context, upload *files.MultipartUpload) (*files.MultipartUpload, error) { - ret := _m.Called(ctx, upload) - - var r0 *files.MultipartUpload - if rf, ok := ret.Get(0).(func(context.Context, *files.MultipartUpload) *files.MultipartUpload); ok { - r0 = rf(ctx, upload) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*files.MultipartUpload) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, *files.MultipartUpload) error); ok { - r1 = rf(ctx, upload) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Upload provides a mock function with given fields: ctx, file -func (_m *Storage) Upload(ctx context.Context, file *files.File) (*files.Upload, error) { - ret := _m.Called(ctx, file) - - var r0 *files.Upload - if rf, ok := ret.Get(0).(func(context.Context, *files.File) *files.Upload); ok { - r0 = rf(ctx, file) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*files.Upload) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, *files.File) error); ok { - r1 = rf(ctx, file) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} diff --git a/pkg/files/uploader.go b/pkg/files/uploader.go new file mode 100644 index 0000000000000000000000000000000000000000..5b03f62a8007c85a64bdaa3ce8961f4d28ceaef3 --- /dev/null +++ b/pkg/files/uploader.go @@ -0,0 +1,42 @@ +package files + +import ( + "errors" + "fmt" + "io" + "net/http" + "net/url" +) + +type Uploader interface { + Upload(src io.Reader, upload *Upload) error +} + +type uploader struct{} + +func NewUploader() Uploader { + return &uploader{} +} + +func (u *uploader) Upload(src io.Reader, upload *Upload) error { + + req, err := http.NewRequest(http.MethodPut, upload.UploadURL, src) + if err != nil { + return err + } + + req.ContentLength = int64(upload.Size) + req.Header.Set("Content-Disposition", fmt.Sprintf("attachment; filename*=UTF-8''%s;", url.PathEscape(upload.Name))) + req.Header.Set("Content-Type", upload.MimeType) + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return err + } + + if resp.StatusCode != http.StatusOK { + return errors.New("upload request failed: " + resp.Status) + } + + return nil +}