-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Phillip/test fileupload #55
base: master
Are you sure you want to change the base?
Changes from 20 commits
7172fc1
4b69c06
6436164
873e72e
43d2858
ad75706
fcc1e69
4bb0843
5e1baf5
fdd9f16
b98dab3
c05a890
4c3d1e5
9b154ea
de28758
3bb7fde
8d06af3
a407051
8e22691
b6f699d
4a9df44
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,7 +14,7 @@ func (a *AppServer) PostCourseEntryHandler() httprouter.Handle { | |
type request struct { | ||
Date time.Time `json:"date"` | ||
Message string `json:"message"` | ||
Pictures []string `json:"pictures"` | ||
Pictures [][]byte `json:"pictures"` | ||
Published bool `json:"published"` | ||
} | ||
type response struct { | ||
|
@@ -43,9 +43,17 @@ func (a *AppServer) PostCourseEntryHandler() httprouter.Handle { | |
return | ||
} | ||
|
||
pURLs, err := url.URLifyStrings(request.Pictures) | ||
err, paths := a.CourseEntryService.StoreCourseEntryFiles(request.Pictures, id, request.Date) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems unusual to me. Aren't files usually uploaded using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the json decoder decodes the base64 encoded bytes-file automagically. |
||
if err != nil { | ||
w.WriteHeader(http.StatusBadRequest) | ||
a.Logger.Printf("error storing files: %v", err) | ||
w.WriteHeader(http.StatusInternalServerError) | ||
return | ||
} | ||
|
||
pURLs, err := url.URLifyStrings(paths) | ||
if err != nil { | ||
a.Logger.Printf("error parsing urls: %v", err) | ||
w.WriteHeader(http.StatusInternalServerError) | ||
return | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,6 +10,7 @@ import ( | |
type AppServer struct { | ||
Host string | ||
Static string | ||
Files string | ||
Logger *log.Logger | ||
UserService eduboard.UserService | ||
UserRepository eduboard.UserRepository | ||
|
@@ -27,11 +28,13 @@ func (a *AppServer) initialize() { | |
privateChain := Chain(protected, Logger(a.Logger), CORS, NewAuthMiddleware(a.UserService)) | ||
publicChain := Chain(public, Logger(a.Logger), CORS) | ||
staticChain := Chain(http.FileServer(http.Dir(a.Static)), Logger(a.Logger), CORS) | ||
filesChain := Chain(http.StripPrefix("/files", http.FileServer(http.Dir(a.Files))), Logger(a.Logger), CORS) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't it be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. http.StripPrefix takes in a string that will be removed from the beginning from the handlers path |
||
|
||
mux := http.NewServeMux() | ||
mux.Handle("/api/v1/", privateChain) | ||
mux.Handle("/api/", publicChain) | ||
mux.Handle("/", staticChain) | ||
mux.Handle("/files/", filesChain) | ||
|
||
a.httpServer = &http.Server{ | ||
Addr: a.Host, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package mock | ||
|
||
type Uploader struct { | ||
UploadFileFn func(file []byte, course string, filename string) (error, string) | ||
UploadFileFnInvoked bool | ||
} | ||
|
||
func (u *Uploader) UploadFile(file []byte, course string, filename string) (error, string) { | ||
u.UploadFileFnInvoked = true | ||
return u.UploadFileFn(file, course, filename) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,18 +2,27 @@ package courseEntryService | |
|
||
import ( | ||
"github.com/eduboard/backend" | ||
"github.com/eduboard/backend/upload" | ||
"github.com/pkg/errors" | ||
"gopkg.in/mgo.v2/bson" | ||
"strconv" | ||
"time" | ||
) | ||
|
||
func New(repository eduboard.CourseEntryRepository) CourseEntryService { | ||
return CourseEntryService{ | ||
ER: repository, | ||
u: &upload.Uploader{}, | ||
} | ||
} | ||
|
||
type Uploader interface { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is this Interface used for? Wasn't the file uploaded to this server? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The interface is used for mocking the upload function in our tests |
||
UploadFile(file []byte, course string, filename string) (error, string) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
} | ||
|
||
type CourseEntryService struct { | ||
ER eduboard.CourseEntryRepository | ||
u Uploader | ||
} | ||
|
||
func (cES CourseEntryService) StoreCourseEntry(entry *eduboard.CourseEntry, cfu eduboard.CourseFindUpdater) (error, *eduboard.CourseEntry) { | ||
|
@@ -39,6 +48,18 @@ func (cES CourseEntryService) StoreCourseEntry(entry *eduboard.CourseEntry, cfu | |
return nil, entry | ||
} | ||
|
||
func (cES CourseEntryService) StoreCourseEntryFiles(files [][]byte, id string, date time.Time) (error, []string) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Again, |
||
paths := []string{} | ||
for key, file := range files { | ||
err, url := cES.u.UploadFile(file, id, date.String()+"_"+strconv.Itoa(key)) | ||
if err != nil { | ||
return err, []string{} | ||
} | ||
paths = append(paths, url) | ||
} | ||
return nil, paths | ||
} | ||
|
||
func (cES CourseEntryService) UpdateCourseEntry(*eduboard.CourseEntry) (*eduboard.CourseEntry, error) { | ||
return &eduboard.CourseEntry{}, nil | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package upload | ||
|
||
import ( | ||
"errors" | ||
"io/ioutil" | ||
"net/http" | ||
"os" | ||
"strings" | ||
) | ||
|
||
type Uploader struct{} | ||
|
||
func (u *Uploader) UploadFile(file []byte, course string, filename string) (error, string) { | ||
// check content type | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Leftover? |
||
dir := string("./files/" + course + "/") | ||
path := string(dir + filename) | ||
serverFile := string("/files/" + course + "/" + filename) | ||
|
||
contentType := http.DetectContentType(file) | ||
|
||
if strings.Split(contentType, "/")[0] != "image" { | ||
return errors.New("filetype not supported"), "" | ||
} | ||
|
||
if _, err := os.Stat(dir); os.IsNotExist(err) { | ||
os.MkdirAll(dir, os.ModePerm) | ||
} | ||
|
||
err := ioutil.WriteFile(path, file, 0644) | ||
if err != nil { | ||
panic(err) | ||
return err, "" | ||
} | ||
|
||
return nil, serverFile | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think about passing a
[]io.Reader
here instead of[][]byte
? That would make any storing / uploading etc way more flexible.