~mendelmaleh/download

905b7e3178cf5ee6d8007c1f39e43c4bd01ebb40 — Mendel E 11 months ago c605361
Add Chan func
1 files changed, 74 insertions(+), 0 deletions(-)

A chan.go
A chan.go => chan.go +74 -0
@@ 0,0 1,74 @@
package download

import (
	"bytes"
	"sync"
)

// FileBuffer is a File with its data downloaded to Buffer.
type FileBuffer struct {
	File
	Buffer *bytes.Buffer
}

// Chan will download data, and send results to a channel.
// The channel will be closed before returning.
func (dl *DL) Chan(data Interface, ch chan FileBuffer, opt *Options) error {
	defer close(ch)

	// set default options
	if opt == nil {
		opt = DefaultOptions
	}

	// ensure opt.MaxGoroutines is positive, otherwise it will hang
	// forever in concurrent mode.
	if opt.Concurrent && opt.MaxGoroutines <= 0 {
		return ErrNoGoroutines
	}

	// get files
	files := data.URLs()
	if len(files) == 0 {
		return ErrNoData
	}

	// download not concurrent
	if !opt.Concurrent {
		for _, f := range files {
			buf, err := dl.try(f.URL, opt.MaxAttempts)
			if err != nil {
				return err
			}

			ch <- FileBuffer{f, buf}
		}

		return nil
	}

	// download concurrent
	var wg sync.WaitGroup
	defer wg.Wait()

	mg := make(chan bool, opt.MaxGoroutines)

	for _, f := range files {
		mg <- true
		wg.Add(1)

		go func(f File) {
			defer wg.Done()
			defer func() { <-mg }()

			buf, err := dl.try(f.URL, opt.MaxAttempts)
			if err != nil {
				panic(err)
			}

			ch <- FileBuffer{f, buf}
		}(f)
	}

	return nil
}