mirror of https://github.com/Xhofe/alist
92 lines
2.2 KiB
Go
92 lines
2.2 KiB
Go
package ftp
|
|
|
|
import (
|
|
"context"
|
|
ftpserver "github.com/KirCute/ftpserverlib-pasvportmap"
|
|
"github.com/alist-org/alist/v3/internal/conf"
|
|
"github.com/alist-org/alist/v3/internal/errs"
|
|
"github.com/alist-org/alist/v3/internal/fs"
|
|
"github.com/alist-org/alist/v3/internal/model"
|
|
"github.com/alist-org/alist/v3/internal/op"
|
|
"github.com/alist-org/alist/v3/internal/stream"
|
|
"github.com/alist-org/alist/v3/server/common"
|
|
"github.com/pkg/errors"
|
|
"io"
|
|
"net/http"
|
|
"os"
|
|
stdpath "path"
|
|
"time"
|
|
)
|
|
|
|
type FileUploadProxy struct {
|
|
ftpserver.FileTransfer
|
|
buffer *os.File
|
|
path string
|
|
ctx context.Context
|
|
}
|
|
|
|
func OpenUpload(ctx context.Context, path string) (*FileUploadProxy, error) {
|
|
user := ctx.Value("user").(*model.User)
|
|
path, err := user.JoinPath(path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
meta, err := op.GetNearestMeta(stdpath.Dir(path))
|
|
if err != nil {
|
|
if !errors.Is(errors.Cause(err), errs.MetaNotFound) {
|
|
return nil, err
|
|
}
|
|
}
|
|
if !(common.CanAccess(user, meta, path, ctx.Value("meta_pass").(string)) &&
|
|
((user.CanFTPManage() && user.CanWrite()) || common.CanWrite(meta, stdpath.Dir(path)))) {
|
|
return nil, errs.PermissionDenied
|
|
}
|
|
tmpFile, err := os.CreateTemp(conf.Conf.TempDir, "file-*")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &FileUploadProxy{buffer: tmpFile, path: path, ctx: ctx}, nil
|
|
}
|
|
|
|
func (f *FileUploadProxy) Read(p []byte) (n int, err error) {
|
|
return 0, errs.NotSupport
|
|
}
|
|
|
|
func (f *FileUploadProxy) Write(p []byte) (n int, err error) {
|
|
return f.buffer.Write(p)
|
|
}
|
|
|
|
func (f *FileUploadProxy) Seek(offset int64, whence int) (int64, error) {
|
|
return 0, errs.NotSupport
|
|
}
|
|
|
|
func (f *FileUploadProxy) Close() error {
|
|
dir, name := stdpath.Split(f.path)
|
|
size, err := f.buffer.Seek(0, io.SeekCurrent)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if _, err := f.buffer.Seek(0, io.SeekStart); err != nil {
|
|
return err
|
|
}
|
|
arr := make([]byte, 512)
|
|
if _, err := f.buffer.Read(arr); err != nil {
|
|
return err
|
|
}
|
|
contentType := http.DetectContentType(arr)
|
|
if _, err := f.buffer.Seek(0, io.SeekStart); err != nil {
|
|
return err
|
|
}
|
|
s := &stream.FileStream{
|
|
Obj: &model.Object{
|
|
Name: name,
|
|
Size: size,
|
|
Modified: time.Now(),
|
|
},
|
|
Mimetype: contentType,
|
|
WebPutAsTask: false,
|
|
}
|
|
s.SetTmpFile(f.buffer)
|
|
return fs.PutDirectly(f.ctx, dir, s, true)
|
|
}
|