mirror of
https://github.com/ipfs/kubo.git
synced 2025-07-19 21:20:31 +08:00
117 lines
2.2 KiB
Go
117 lines
2.2 KiB
Go
package files
|
|
|
|
import (
|
|
"io"
|
|
"io/ioutil"
|
|
"mime"
|
|
"mime/multipart"
|
|
"net/url"
|
|
)
|
|
|
|
const (
|
|
multipartFormdataType = "multipart/form-data"
|
|
multipartMixedType = "multipart/mixed"
|
|
|
|
applicationDirectory = "application/x-directory"
|
|
applicationSymlink = "application/symlink"
|
|
applicationFile = "application/octet-stream"
|
|
|
|
contentTypeHeader = "Content-Type"
|
|
)
|
|
|
|
// MultipartFile implements File, and is created from a `multipart.Part`.
|
|
// It can be either a directory or file (checked by calling `IsDirectory()`).
|
|
type MultipartFile struct {
|
|
File
|
|
|
|
Part *multipart.Part
|
|
Reader *multipart.Reader
|
|
Mediatype string
|
|
}
|
|
|
|
func NewFileFromPart(part *multipart.Part) (File, error) {
|
|
f := &MultipartFile{
|
|
Part: part,
|
|
}
|
|
|
|
contentType := part.Header.Get(contentTypeHeader)
|
|
switch contentType {
|
|
case applicationSymlink:
|
|
out, err := ioutil.ReadAll(part)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &Symlink{
|
|
Target: string(out),
|
|
name: f.FileName(),
|
|
}, nil
|
|
case applicationFile:
|
|
return &ReaderFile{
|
|
reader: part,
|
|
filename: f.FileName(),
|
|
abspath: part.Header.Get("abspath"),
|
|
fullpath: f.FullPath(),
|
|
}, nil
|
|
}
|
|
|
|
var err error
|
|
f.Mediatype, _, err = mime.ParseMediaType(contentType)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return f, nil
|
|
}
|
|
|
|
func (f *MultipartFile) IsDirectory() bool {
|
|
return f.Mediatype == multipartFormdataType || f.Mediatype == applicationDirectory
|
|
}
|
|
|
|
func (f *MultipartFile) NextFile() (File, error) {
|
|
if !f.IsDirectory() {
|
|
return nil, ErrNotDirectory
|
|
}
|
|
if f.Reader != nil {
|
|
part, err := f.Reader.NextPart()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return NewFileFromPart(part)
|
|
}
|
|
|
|
return nil, io.EOF
|
|
}
|
|
|
|
func (f *MultipartFile) FileName() string {
|
|
if f == nil || f.Part == nil {
|
|
return ""
|
|
}
|
|
|
|
filename, err := url.QueryUnescape(f.Part.FileName())
|
|
if err != nil {
|
|
// if there is a unescape error, just treat the name as unescaped
|
|
return f.Part.FileName()
|
|
}
|
|
return filename
|
|
}
|
|
|
|
func (f *MultipartFile) FullPath() string {
|
|
return f.FileName()
|
|
}
|
|
|
|
func (f *MultipartFile) Read(p []byte) (int, error) {
|
|
if f.IsDirectory() {
|
|
return 0, ErrNotReader
|
|
}
|
|
return f.Part.Read(p)
|
|
}
|
|
|
|
func (f *MultipartFile) Close() error {
|
|
if f.IsDirectory() {
|
|
return ErrNotReader
|
|
}
|
|
return f.Part.Close()
|
|
}
|