Files
cloudpods/pkg/apigateway/handler/imageutils.go
2021-07-16 12:20:52 +08:00

147 lines
3.3 KiB
Go

// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package handler
import (
"bytes"
"context"
"fmt"
"io"
"mime/multipart"
"net/http"
"strconv"
"time"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/onecloud/pkg/appsrv"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient/auth"
"yunion.io/x/onecloud/pkg/mcclient/modules"
)
func readImageForm(r *multipart.Reader) (map[string]string, *multipart.Part, error) {
params := make(map[string]string)
maxValueBytes := int64(10 << 20)
for {
p, err := r.NextPart()
if err == io.EOF {
break
}
if err != nil {
return nil, nil, err
}
name := p.FormName()
if name == "" {
continue
}
filename := p.FileName()
var b bytes.Buffer
_, hasContentTypeHeader := p.Header["Content-Type"]
if !hasContentTypeHeader && filename == "" {
// value, store as string in memory
n, err := io.CopyN(&b, p, maxValueBytes+1)
if err != nil && err != io.EOF {
return nil, nil, err
}
maxValueBytes -= n
if maxValueBytes < 0 {
return nil, nil, multipart.ErrMessageTooLarge
}
params[name] = b.String()
continue
}
if name == "image" || name == "file" {
return params, p, nil
} else {
return nil, nil, fmt.Errorf("no file uploaded")
}
}
return nil, nil, fmt.Errorf("empty form")
}
func imageUploadHandler(ctx context.Context, w http.ResponseWriter, r *http.Request) {
const (
invalidForm = "invalid form"
)
reader, e := r.MultipartReader()
if e != nil {
httperrors.InvalidInputError(ctx, w, invalidForm)
return
}
p, f, e := readImageForm(reader)
if e != nil {
httperrors.InvalidInputError(ctx, w, invalidForm)
return
}
params := jsonutils.NewDict()
name, ok := p["name"]
if !ok {
httperrors.InvalidInputError(ctx, w, "missing image name")
return
}
params.Add(jsonutils.NewString(name), "name")
_imageSize, ok := p["image_size"]
if !ok {
httperrors.InvalidInputError(ctx, w, "missing image size")
return
}
imageSize, e := strconv.ParseInt(_imageSize, 10, 64)
if e != nil {
httperrors.InvalidInputError(ctx, w, "invalid image size")
return
}
// add all other params
for k, v := range p {
if k == "name" || k == "image_size" {
continue
}
params.Add(jsonutils.NewString(v), k)
}
token := AppContextToken(ctx)
s := auth.GetSession(ctx, token, FetchRegion(r), "")
res, e := modules.Images.Upload(s, params, f, imageSize)
if e != nil {
httperrors.GeneralServerError(ctx, w, e)
return
} else {
appsrv.SendJSON(w, res)
}
}
func uploadHandlerInfo(method, prefix string, handler func(context.Context, http.ResponseWriter, *http.Request)) *appsrv.SHandlerInfo {
log.Debugf("%s - %s", method, prefix)
hi := appsrv.SHandlerInfo{}
hi.SetMethod(method)
hi.SetPath(prefix)
hi.SetHandler(handler)
hi.SetProcessTimeout(6 * time.Hour)
hi.SetWorkerManager(GetUploaderWorker())
return &hi
}