"Fossies" - the Fresh Open Source Software Archive

Member "gdrive-2.1.1/drive/upload.go" (28 May 2021, 6395 Bytes) of package /linux/misc/gdrive-2.1.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Go source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 package drive
    2 
    3 import (
    4     "fmt"
    5     "google.golang.org/api/drive/v3"
    6     "google.golang.org/api/googleapi"
    7     "io"
    8     "mime"
    9     "os"
   10     "path/filepath"
   11     "time"
   12 )
   13 
   14 type UploadArgs struct {
   15     Out         io.Writer
   16     Progress    io.Writer
   17     Path        string
   18     Name        string
   19     Description string
   20     Parents     []string
   21     Mime        string
   22     Recursive   bool
   23     Share       bool
   24     Delete      bool
   25     ChunkSize   int64
   26     Timeout     time.Duration
   27 }
   28 
   29 func (self *Drive) Upload(args UploadArgs) error {
   30     if args.ChunkSize > intMax()-1 {
   31         return fmt.Errorf("Chunk size is to big, max chunk size for this computer is %d", intMax()-1)
   32     }
   33 
   34     // Ensure that none of the parents are sync dirs
   35     for _, parent := range args.Parents {
   36         isSyncDir, err := self.isSyncFile(parent)
   37         if err != nil {
   38             return err
   39         }
   40 
   41         if isSyncDir {
   42             return fmt.Errorf("%s is a sync directory, use 'sync upload' instead", parent)
   43         }
   44     }
   45 
   46     if args.Recursive {
   47         return self.uploadRecursive(args)
   48     }
   49 
   50     info, err := os.Stat(args.Path)
   51     if err != nil {
   52         return fmt.Errorf("Failed stat file: %s", err)
   53     }
   54 
   55     if info.IsDir() {
   56         return fmt.Errorf("'%s' is a directory, use --recursive to upload directories", info.Name())
   57     }
   58 
   59     f, rate, err := self.uploadFile(args)
   60     if err != nil {
   61         return err
   62     }
   63     fmt.Fprintf(args.Out, "Uploaded %s at %s/s, total %s\n", f.Id, formatSize(rate, false), formatSize(f.Size, false))
   64 
   65     if args.Share {
   66         err = self.shareAnyoneReader(f.Id)
   67         if err != nil {
   68             return err
   69         }
   70 
   71         fmt.Fprintf(args.Out, "File is readable by anyone at %s\n", f.WebContentLink)
   72     }
   73 
   74     if args.Delete {
   75         err = os.Remove(args.Path)
   76         if err != nil {
   77             return fmt.Errorf("Failed to delete file: %s", err)
   78         }
   79         fmt.Fprintf(args.Out, "Removed %s\n", args.Path)
   80     }
   81 
   82     return nil
   83 }
   84 
   85 func (self *Drive) uploadRecursive(args UploadArgs) error {
   86     info, err := os.Stat(args.Path)
   87     if err != nil {
   88         return fmt.Errorf("Failed stat file: %s", err)
   89     }
   90 
   91     if info.IsDir() {
   92         args.Name = ""
   93         return self.uploadDirectory(args)
   94     } else if info.Mode().IsRegular() {
   95         _, _, err := self.uploadFile(args)
   96         return err
   97     }
   98 
   99     return nil
  100 }
  101 
  102 func (self *Drive) uploadDirectory(args UploadArgs) error {
  103     srcFile, srcFileInfo, err := openFile(args.Path)
  104     if err != nil {
  105         return err
  106     }
  107 
  108     // Close file on function exit
  109     defer srcFile.Close()
  110 
  111     fmt.Fprintf(args.Out, "Creating directory %s\n", srcFileInfo.Name())
  112     // Make directory on drive
  113     f, err := self.mkdir(MkdirArgs{
  114         Out:         args.Out,
  115         Name:        srcFileInfo.Name(),
  116         Parents:     args.Parents,
  117         Description: args.Description,
  118     })
  119     if err != nil {
  120         return err
  121     }
  122 
  123     // Read files from directory
  124     names, err := srcFile.Readdirnames(0)
  125     if err != nil && err != io.EOF {
  126         return fmt.Errorf("Failed reading directory: %s", err)
  127     }
  128 
  129     for _, name := range names {
  130         // Copy args and set new path and parents
  131         newArgs := args
  132         newArgs.Path = filepath.Join(args.Path, name)
  133         newArgs.Parents = []string{f.Id}
  134         newArgs.Description = ""
  135 
  136         // Upload
  137         err = self.uploadRecursive(newArgs)
  138         if err != nil {
  139             return err
  140         }
  141     }
  142 
  143     return nil
  144 }
  145 
  146 func (self *Drive) uploadFile(args UploadArgs) (*drive.File, int64, error) {
  147     srcFile, srcFileInfo, err := openFile(args.Path)
  148     if err != nil {
  149         return nil, 0, err
  150     }
  151 
  152     // Close file on function exit
  153     defer srcFile.Close()
  154 
  155     // Instantiate empty drive file
  156     dstFile := &drive.File{Description: args.Description}
  157 
  158     // Use provided file name or use filename
  159     if args.Name == "" {
  160         dstFile.Name = filepath.Base(srcFileInfo.Name())
  161     } else {
  162         dstFile.Name = args.Name
  163     }
  164 
  165     // Set provided mime type or get type based on file extension
  166     if args.Mime == "" {
  167         dstFile.MimeType = mime.TypeByExtension(filepath.Ext(dstFile.Name))
  168     } else {
  169         dstFile.MimeType = args.Mime
  170     }
  171 
  172     // Set parent folders
  173     dstFile.Parents = args.Parents
  174 
  175     // Chunk size option
  176     chunkSize := googleapi.ChunkSize(int(args.ChunkSize))
  177 
  178     // Wrap file in progress reader
  179     progressReader := getProgressReader(srcFile, args.Progress, srcFileInfo.Size())
  180 
  181     // Wrap reader in timeout reader
  182     reader, ctx := getTimeoutReaderContext(progressReader, args.Timeout)
  183 
  184     fmt.Fprintf(args.Out, "Uploading %s\n", args.Path)
  185     started := time.Now()
  186 
  187     f, err := self.service.Files.Create(dstFile).Fields("id", "name", "size", "md5Checksum", "webContentLink").Context(ctx).Media(reader, chunkSize).Do()
  188     if err != nil {
  189         if isTimeoutError(err) {
  190             return nil, 0, fmt.Errorf("Failed to upload file: timeout, no data was transferred for %v", args.Timeout)
  191         }
  192         return nil, 0, fmt.Errorf("Failed to upload file: %s", err)
  193     }
  194 
  195     // Calculate average upload rate
  196     rate := calcRate(f.Size, started, time.Now())
  197 
  198     return f, rate, nil
  199 }
  200 
  201 type UploadStreamArgs struct {
  202     Out         io.Writer
  203     In          io.Reader
  204     Name        string
  205     Description string
  206     Parents     []string
  207     Mime        string
  208     Share       bool
  209     ChunkSize   int64
  210     Progress    io.Writer
  211     Timeout     time.Duration
  212 }
  213 
  214 func (self *Drive) UploadStream(args UploadStreamArgs) error {
  215     if args.ChunkSize > intMax()-1 {
  216         return fmt.Errorf("Chunk size is to big, max chunk size for this computer is %d", intMax()-1)
  217     }
  218 
  219     // Instantiate empty drive file
  220     dstFile := &drive.File{Name: args.Name, Description: args.Description}
  221 
  222     // Set mime type if provided
  223     if args.Mime != "" {
  224         dstFile.MimeType = args.Mime
  225     }
  226 
  227     // Set parent folders
  228     dstFile.Parents = args.Parents
  229 
  230     // Chunk size option
  231     chunkSize := googleapi.ChunkSize(int(args.ChunkSize))
  232 
  233     // Wrap file in progress reader
  234     progressReader := getProgressReader(args.In, args.Progress, 0)
  235 
  236     // Wrap reader in timeout reader
  237     reader, ctx := getTimeoutReaderContext(progressReader, args.Timeout)
  238 
  239     fmt.Fprintf(args.Out, "Uploading %s\n", dstFile.Name)
  240     started := time.Now()
  241 
  242     f, err := self.service.Files.Create(dstFile).Fields("id", "name", "size", "webContentLink").Context(ctx).Media(reader, chunkSize).Do()
  243     if err != nil {
  244         if isTimeoutError(err) {
  245             return fmt.Errorf("Failed to upload file: timeout, no data was transferred for %v", args.Timeout)
  246         }
  247         return fmt.Errorf("Failed to upload file: %s", err)
  248     }
  249 
  250     // Calculate average upload rate
  251     rate := calcRate(f.Size, started, time.Now())
  252 
  253     fmt.Fprintf(args.Out, "Uploaded %s at %s/s, total %s\n", f.Id, formatSize(rate, false), formatSize(f.Size, false))
  254     if args.Share {
  255         err = self.shareAnyoneReader(f.Id)
  256         if err != nil {
  257             return err
  258         }
  259 
  260         fmt.Fprintf(args.Out, "File is readable by anyone at %s\n", f.WebContentLink)
  261     }
  262     return nil
  263 }