Skip to content

Commit

Permalink
refactor: Upload to be consistent with share file
Browse files Browse the repository at this point in the history
Signed-off-by: Vincent Boutour <[email protected]>
  • Loading branch information
ViBiOh committed Aug 27, 2024
1 parent 2fe21e3 commit f9b86ad
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 78 deletions.
1 change: 1 addition & 0 deletions cmd/fibr/static/styles/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ input {

input[type="file"] {
color: var(--white);
width: 80%;
}

a {
Expand Down
2 changes: 1 addition & 1 deletion cmd/fibr/static/styles/main.min.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 17 additions & 8 deletions pkg/crud/post.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,15 +116,24 @@ func (s Service) handleMultipart(w http.ResponseWriter, r *http.Request, request
return
}

fileName, filePath, err := getUploadNameAndPath(request, values["filename"], file)
if err != nil {
s.error(w, r, request, model.WrapInvalid(fmt.Errorf("get upload name: %w", err)))
return
}

if values["overwrite"] != "true" {
_, filePath, err := getUploadNameAndPath(request, values["filename"], file)
if err != nil {
s.error(w, r, request, model.WrapInvalid(err))
if _, err := s.storage.Stat(ctx, filePath); err == nil {
s.error(w, r, request, model.WrapInvalid(fmt.Errorf("filepath `%s`: %w", filePath, ErrFileAlreadyExists)))
return
}
}

if _, err := s.storage.Stat(ctx, filePath); err == nil {
s.error(w, r, request, model.WrapInvalid(fmt.Errorf("filename `%s`: %w", filePath, ErrFileAlreadyExists)))
var size int64
if rawSize := values["size"]; len(rawSize) == 0 {
size, err = getUploadSize(rawSize)
if err != nil {
s.error(w, r, request, model.WrapInvalid(fmt.Errorf("get upload size `%s`: %w", rawSize, err)))
return
}
}
Expand All @@ -139,14 +148,14 @@ func (s Service) handleMultipart(w http.ResponseWriter, r *http.Request, request
chunkNumber = fmt.Sprintf("%010d", chunkNumberValue)

telemetry.SetRouteTag(ctx, "/chunk")
s.uploadChunk(w, r, request, values["filename"], chunkNumber, file)
s.uploadChunk(w, r, request, fileName, chunkNumber, file)
} else {
telemetry.SetRouteTag(ctx, "/merge")
s.mergeChunk(w, r, request, values)
s.mergeChunk(w, r, request, fileName, filePath, size)
}
} else {
telemetry.SetRouteTag(ctx, "/upload")
s.upload(w, r, request, values, file)
s.upload(w, r, request, fileName, filePath, size, file)
}
}

Expand Down
39 changes: 16 additions & 23 deletions pkg/crud/upload.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,15 @@ import (
"path"
"strconv"

absto "github.com/ViBiOh/absto/pkg/model"
"github.com/ViBiOh/fibr/pkg/provider"
"github.com/ViBiOh/httputils/v4/pkg/model"
"github.com/ViBiOh/httputils/v4/pkg/renderer"
"github.com/ViBiOh/httputils/v4/pkg/telemetry"
)

func (s Service) saveUploadedFile(ctx context.Context, request provider.Request, inputName, rawSize string, file *multipart.Part) (fileName string, err error) {
var filePath string

fileName, filePath, err = getUploadNameAndPath(request, inputName, file)
if err != nil {
return "", fmt.Errorf("get upload name: %w", err)
}

var size int64
size, err = getUploadSize(rawSize)
if err != nil {
return "", fmt.Errorf("get upload size: %w", err)
}

err = provider.WriteToStorage(ctx, s.storage, filePath, size, file)
func (s Service) saveUploadedFile(ctx context.Context, request provider.Request, filePath string, size int64, file *multipart.Part) error {
err := provider.WriteToStorage(ctx, s.storage, filePath, size, file)

if err == nil {
go func(ctx context.Context) {
Expand All @@ -42,7 +30,7 @@ func (s Service) saveUploadedFile(ctx context.Context, request provider.Request,
}(context.WithoutCancel(ctx))
}

return fileName, err
return err
}

func getUploadNameAndPath(request provider.Request, inputName string, part *multipart.Part) (fileName string, filePath string, err error) {
Expand All @@ -56,10 +44,14 @@ func getUploadNameAndPath(request provider.Request, inputName string, part *mult
fileName = part.FileName()
}

fileName, err = provider.SanitizeName(fileName, true)
if err != nil {
if err = absto.ValidPath(fileName); err != nil {
return
}

if fileName, err = provider.SanitizeName(fileName, true); err != nil {
return
}

filePath = request.SubPath(fileName)

return
Expand All @@ -77,22 +69,23 @@ func getUploadSize(rawSize string) (int64, error) {
return size, nil
}

func (s Service) upload(w http.ResponseWriter, r *http.Request, request provider.Request, values map[string]string, file *multipart.Part) {
func (s Service) upload(w http.ResponseWriter, r *http.Request, request provider.Request, fileName, filePath string, size int64, file *multipart.Part) {
if file == nil {
s.error(w, r, request, model.WrapInvalid(errors.New("no file provided for save")))
return
}

var err error

ctx, end := telemetry.StartSpan(r.Context(), s.tracer, "upload")
defer end(nil)
defer end(&err)

filename, err := s.saveUploadedFile(ctx, request, values["filename"], values["size"], file)
if err != nil {
if err = s.saveUploadedFile(ctx, request, filePath, size, file); err != nil {
s.error(w, r, request, model.WrapInternal(err))
return
}

s.postUpload(w, r, request, filename)
s.postUpload(w, r, request, fileName)
}

func (s Service) postUpload(w http.ResponseWriter, r *http.Request, request provider.Request, fileName string) {
Expand Down
56 changes: 10 additions & 46 deletions pkg/crud/upload_chunk.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,16 @@ func (s Service) uploadChunk(w http.ResponseWriter, r *http.Request, request pro
return
}

fileName, err := safeFilename(fileName)
if err != nil {
s.error(w, r, request, model.WrapInvalid(err))
return
}

tempDestination := filepath.Join(s.temporaryFolder, provider.Hash(fileName))
tempFile := filepath.Join(tempDestination, chunkNumber)

if err = os.MkdirAll(tempDestination, absto.DirectoryPerm); err != nil {
if err := os.MkdirAll(tempDestination, absto.DirectoryPerm); err != nil {
s.error(w, r, request, model.WrapInternal(err))
return
}

var writer *os.File
writer, err = os.OpenFile(tempFile, os.O_RDWR|os.O_CREATE|os.O_TRUNC, absto.RegularFilePerm)
writer, err := os.OpenFile(tempFile, os.O_RDWR|os.O_CREATE|os.O_TRUNC, absto.RegularFilePerm)
if err != nil {
return
}
Expand All @@ -67,46 +61,29 @@ func (s Service) uploadChunk(w http.ResponseWriter, r *http.Request, request pro
w.WriteHeader(http.StatusAccepted)
}

func (s Service) mergeChunk(w http.ResponseWriter, r *http.Request, request provider.Request, values map[string]string) {
ctx, end := telemetry.StartSpan(r.Context(), s.tracer, "merge_chunk")
defer end(nil)
func (s Service) mergeChunk(w http.ResponseWriter, r *http.Request, request provider.Request, fileName, filePath string, size int64) {
var err error

fileName, err := safeFilename(values["filename"])
if err != nil {
s.error(w, r, request, model.WrapInvalid(err))
return
}
ctx, end := telemetry.StartSpan(r.Context(), s.tracer, "merge_chunk")
defer end(&err)

tempFolder := filepath.Join(s.temporaryFolder, provider.Hash(fileName))
tempFile := filepath.Join(tempFolder, fileName)

if err := s.mergeChunkFiles(ctx, tempFolder, tempFile); err != nil {
s.error(w, r, request, model.WrapInternal(err))
return
}

var size int64
size, err = getUploadSize(values["size"])
if err != nil {
if err = s.mergeChunkFiles(ctx, tempFolder, tempFile); err != nil {
s.error(w, r, request, model.WrapInternal(err))
return
}

file, err := os.Open(tempFile)
if err != nil {
s.error(w, r, request, model.WrapInternal(err))
return
}
var file *os.File

fileName, err = provider.SanitizeName(fileName, true)
file, err = os.Open(tempFile)
if err != nil {
s.error(w, r, request, model.WrapInternal(err))
return
}

filePath := request.SubPath(fileName)
err = provider.WriteToStorage(ctx, s.storage, filePath, size, file)
if err != nil {
if err = provider.WriteToStorage(ctx, s.storage, filePath, size, file); err != nil {
s.error(w, r, request, model.WrapInternal(err))
return
}
Expand Down Expand Up @@ -181,16 +158,3 @@ func browseChunkFiles(ctx context.Context, directory, destination string, writer
return nil
})
}

func safeFilename(fileName string) (string, error) {
if err := absto.ValidPath(fileName); err != nil {
return fileName, err
}

output, err := provider.SanitizeName(fileName, true)
if err != nil {
return fileName, fmt.Errorf("sanitize: %w", err)
}

return output, nil
}

0 comments on commit f9b86ad

Please sign in to comment.