func (f *File) getHeadObject() (*s3.HeadObjectOutput, error) {
	headObjectInput := new(s3.HeadObjectInput).SetKey(f.key).SetBucket(f.bucket)
	client, err := f.fileSystem.Client()
	if err != nil {
		return nil, err
	}
	return client.HeadObject(headObjectInput)
}
/*
Private helper functions
package s3
import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"net/url"
	"os"
	"path"
	"time"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/service/s3"
	"github.com/aws/aws-sdk-go/service/s3/s3iface"
	"github.com/aws/aws-sdk-go/service/s3/s3manager"
	"github.com/c2fo/vfs/v6"
	"github.com/c2fo/vfs/v6/backend"
	"github.com/c2fo/vfs/v6/mocks"
	"github.com/c2fo/vfs/v6/utils"
)
type File struct {
	fileSystem  *FileSystem
	bucket      string
	key         string
	tempFile    *os.File
	writeBuffer *bytes.Buffer
}
type Downloader interface {
	Download(w io.WriterAt, input *s3.GetObjectInput, options ...func(downloader *s3manager.Downloader)) (n int64, err error)
	DownloadWithContext(ctx aws.Context, w io.WriterAt, input *s3.GetObjectInput, options ...func(*s3manager.Downloader)) (n int64, err error)
	DownloadWithIterator(ctx aws.Context, iter s3manager.BatchDownloadIterator, opts ...func(*s3manager.Downloader)) error
}
func (f *File) LastModified() (*time.Time, error) {
	head, err := f.getHeadObject()
	if err != nil {
		return nil, err
	}
	return head.LastModified, nil
}
func (f *File) Name() string {
	return path.Base(f.key)
}
func (f *File) Path() string {
	return utils.EnsureLeadingSlash(f.key)
}
func (f *File) Exists() (bool, error) {
	_, err := f.getHeadObject()
	code := ""
	if err != nil {
		code = err.(awserr.Error).Code()
	}
	if err != nil && (code == s3.ErrCodeNoSuchKey || code == "NotFound") {
		return false, nil
	} else if err != nil {
		return false, err
	}
	return true, nil
}
func (f *File) Size() (uint64, error) {
	head, err := f.getHeadObject()
	if err != nil {
		return 0, err
	}
	return uint64(*head.ContentLength), nil
}
func (f *File) Location() vfs.Location {
	return vfs.Location(&Location{
		fileSystem: f.fileSystem,
		prefix:     path.Dir(f.key),
		bucket:     f.bucket,
	})
}
func (f *File) CopyToFile(file vfs.File) error {
	if err := backend.ValidateCopySeekPosition(f); err != nil {
		return err
	}
	if tf, ok := file.(*File); ok {
		input, err := f.getCopyObjectInput(tf)
		if err != nil {
			return err
		}
		if input != nil {
			client, err := f.fileSystem.Client()
			if err != nil {
				return err
			}
			_, err = client.CopyObject(input)
			return err
		}
	}
	fileBufferSize := 0
	if opts, ok := f.Location().FileSystem().(*FileSystem).options.(Options); ok {
		fileBufferSize = opts.FileBufferSize
	}
	if err := utils.TouchCopyBuffered(file, f, fileBufferSize); err != nil {
		return err
	}
	if cerr := file.Close(); cerr != nil {
		return cerr
	}
	return f.Close()
}
func (f *File) MoveToFile(file vfs.File) error {
	if err := f.CopyToFile(file); err != nil {
		return err
	}
	return f.Delete()
}
func (f *File) MoveToLocation(location vfs.Location) (vfs.File, error) {
	newFile, err := f.CopyToLocation(location)
	if err != nil {
		return nil, err
	}
	delErr := f.Delete()
	return newFile, delErr
}
func (f *File) CopyToLocation(location vfs.Location) (vfs.File, error) {
	newFile, err := location.NewFile(f.Name())
	if err != nil {
		return nil, err
	}
	return newFile, f.CopyToFile(newFile)
}
func (f *File) Delete() error {
	f.writeBuffer = nil
	if err := f.Close(); err != nil {
		return err
	}
	client, err := f.fileSystem.Client()
	if err != nil {
		return err
	}
	_, err = client.DeleteObject(&s3.DeleteObjectInput{
		Key:    &f.key,
		Bucket: &f.bucket,
	})
	return err
}
func (f *File) Close() error {
	if f.tempFile != nil {
		err := f.tempFile.Close()
		if err != nil {
			return err
		}
		err = os.Remove(f.tempFile.Name())
		if err != nil && !os.IsNotExist(err) {
			return err
		}
		f.tempFile = nil
	}
	if f.writeBuffer != nil {
		client, err := f.fileSystem.Client()
		if err != nil {
			return err
		}
		uploader := s3manager.NewUploaderWithClient(client)
		uploadInput := uploadInput(f)
		uploadInput.Body = f.writeBuffer
		_, err = uploader.Upload(uploadInput)
		if err != nil {
			return err
		}
		f.writeBuffer = nil
		return waitUntilFileExists(f, 5)
	}
	return nil
}
func (f *File) Read(p []byte) (n int, err error) {
	if err := f.checkTempFile(); err != nil {
		return 0, err
	}
	return f.tempFile.Read(p)
}
func (f *File) Seek(offset int64, whence int) (int64, error) {
	if err := f.checkTempFile(); err != nil {
		return 0, err
	}
	return f.tempFile.Seek(offset, whence)
}
func (f *File) Write(data []byte) (res int, err error) {
	if f.writeBuffer == nil {
		f.writeBuffer = bytes.NewBuffer([]byte{})
	}
	return f.writeBuffer.Write(data)
}
func (f *File) Touch() error {
	exists, err := f.Exists()
	if err != nil {
		return err
	}
	if !exists {
		_, err = f.Write([]byte(""))
		if err != nil {
			return err
		}
		if err := f.Close(); err != nil {
			return err
		}
	} else {
		return utils.UpdateLastModifiedByMoving(f)
	}
	return nil
}
func (f *File) URI() string {
	return utils.GetFileURI(f)
}
func (f *File) String() string {
	return f.URI()
}