Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to retrieve multiple files continuously #719

Closed
HuanjunKong opened this issue Oct 15, 2016 · 8 comments
Closed

How to retrieve multiple files continuously #719

HuanjunKong opened this issue Oct 15, 2016 · 8 comments
Assignees
Labels

Comments

@HuanjunKong
Copy link

HuanjunKong commented Oct 15, 2016

After checking #562 , I post 10 images (500KB) to gin, code :

    func extractImgs(c *gin.Context) {
        prefix := "prefix"
        for ix := 0; ix < 10; ix++ {
            file, _, err := c.Request.FormFile(prefix + strconv.Itoa(ix))
            if err != nil {
                // do sth.
                return
            }
            // call face recognition algorithm
            face_rec_async(file)
        }
    }

c.Request.FormFile cost a lot time. It seems like that FormFile returns file after retrieved all 10 files.

Face recognition is time-consuming algorithm, this workflow should be better:

retrieve first file -> recognize face -> retrieve second file -> recognition -> ... ,

just like a link list.

My question is how to retrieve files like traverse linked list.

@milne-dev
Copy link

I have found a way that works by turning the multipart form into a reader. Here is a code snippet without full error handling:

reader, _ := c.Request.MultipartReader()

for {
    if part, err := reader.NextPart(); err == io.EOF {
        break
    }

    // part implements io.Reader
}

@javierprovecho
Copy link
Member

@HuanjunKong sorry for late reply, .FormFile() is a wrap from net/http. If the form hasn't been parsed yet, it process all files by creating for each one a File object. After looking through the code, here should not be any delay after calling for the first file.

@Michael77 is another solution but I see that you could not access directly a file by name.

@jeffkoncz
Copy link

jeffkoncz commented Jan 12, 2017

I had to do something similar--transferring multiple file uploads to S3 in parallel. Adding to @Michael77 method if you need access to the original filename you can use the mime package.

disposition, params, err := mime.ParseMediaType(part.Header.Get("Content-Disposition"))
if err != nil {
  break
}
filename := params["filename"]

@svperfecta
Copy link

hey @jeffkoncz any chance you have a larger example of this? I'm a bit stuck, doing the exact same thing.

@appleboy
Copy link
Member

appleboy commented Feb 4, 2017

@jeffkoncz
Copy link

jeffkoncz commented Feb 4, 2017

@genexp Here's some code that is specific to transferring multiple file uploads to S3. Hopefully it can get you unstuck :) :

func MultipartUploadHandler(c *gin.Context) {
	multipart, err := c.Request.MultipartReader()
	if err != nil {
		log.Fatalln("Failed to create MultipartReader", err)
	}

	for {
		mimePart, err := multipart.NextPart()
		if err == io.EOF {
			break
		}
		if err != nil {
			log.Printf("Error reading multipart section: %v", err)
			break
		}
		disposition, params, err := mime.ParseMediaType(mimePart.Header.Get("Content-Disposition"))
		if err != nil {
			log.Printf("Invalid Content-Disposition: %v", err)
			break
		}

		// S3 Upload Manager
		uploader := s3manager.NewUploader(session.New(&aws.Config{Region: aws.String("us-west-2")}))
		result, err := uploader.Upload(&s3manager.UploadInput{
			Body:   mimePart,
			Bucket: aws.String("yourbucket"),
			Key:    aws.String(params["filename"]),
			ContentType: aws.String(mimePart.Header.Get("Content-Type")),
			ACL: aws.String("public-read"),
		})
		if err != nil {
			log.Fatalln("Failed to upload to S3", err)
		}
		
		c.JSON(http.StatusOK, gin.H{
			"location": result.Location,
		})
	}
}

@svperfecta
Copy link

@jeffkoncz Yeah, this is awesome. Thanks so much!

@geoherna
Copy link

Awesome! Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

7 participants