/** Check a value against a bounded(!) buffer */ func valCheck(buffer []byte, refVal []byte, checkedVal *multipart.Part) bool { totalBytesRead := 0 bufferLength := len(buffer) for { if totalBytesRead >= bufferLength { break } bytesRead, err := checkedVal.Read(buffer[totalBytesRead:]) if bytesRead < 0 || err == io.EOF { break } totalBytesRead += bytesRead } i := 0 refValLength := len(refVal) if totalBytesRead != refValLength { return false } for i < refValLength { if refVal[i] != buffer[i] { return false } i++ } return true }
func WriteFileChunk(chunk *multipart.Part, file *os.File) error { buffer := make([]byte, 4096) bufbytes, err := chunk.Read(buffer) if err == io.EOF { return err } file.Write(buffer[:bufbytes]) return err }
func ConsumePart(p *multipart.Part, sz int, f func([]byte, int) (interface{}, error)) (interface{}, error) { value := make([]byte, sz, sz) n, err := p.Read(value) if err != nil { return nil, err } i, err := f(value, n) if err != nil { return nil, err } return i, err }
func getParam(part *multipart.Part) (string, float32, error) { name := part.FormName() fmt.Printf("Read name %s", name) if name == "submit" { return name, float32(0), nil } buffer := make([]byte, 1024) n, err := part.Read(buffer) fmt.Printf("Read %s", string(buffer[:n])) if err != nil { return "", 0.0, err } value, err := strconv.ParseFloat(string(buffer[:n]), 32) if err != nil { return "", 0.0, err } return name, float32(value), nil }
func (r *Resumable) ReadBody(p *multipart.Part, c *Chunk) error { data := make([]byte, r.MaxChunkSize) // read := 0 // TODO: find a way to identify oversized chunks (read > r.MaxChunkSize?) for { n, err := p.Read(data) // read += n if err != nil { if err == io.EOF { break } else { return err } } c.Body = append(c.Body, data[:n]...) } return nil }
/** Uploader has a function to drain an http request off to a filename Note that writing to a file is not the only possible course of action. The part name (or file name, content type, etc) may insinuate that the file is small, and should be held in memory. */ func (h uploader) serveHTTPUploadPOSTDrain(fileName string, w http.ResponseWriter, part *multipart.Part) (bytesWritten int64, partsWritten int64) { log.Printf("read part %s", fileName) //Dangerous... Should whitelist char names to prevent writes //outside the homeBucket! drainTo, drainErr := os.Create(fileName) defer drainTo.Close() if drainErr != nil { log.Printf("cannot write out file %s, %v", fileName, drainErr) http.Error(w, "cannot write out file", 500) return bytesWritten, partsWritten } drain := bufio.NewWriter(drainTo) var lastBytesRead int buffer := make([]byte, h.BufferSize) for lastBytesRead >= 0 { bytesRead, berr := part.Read(buffer) lastBytesRead = bytesRead if berr == io.EOF { break } if berr != nil { log.Printf("error reading data! %v", berr) http.Error(w, "error reading data", 500) return bytesWritten, partsWritten } if lastBytesRead > 0 { bytesWritten += int64(lastBytesRead) drain.Write(buffer[:bytesRead]) partsWritten++ } } drain.Flush() log.Printf("wrote file %s of length %d", fileName, bytesWritten) //Watchout for hardcoding. This is here to make it convenient to retrieve what you downloaded log.Printf("https://127.0.0.1:%d/download/%s", h.Port, fileName[1+len(h.HomeBucket):]) return bytesWritten, partsWritten }
func write_file(part *multipart.Part) error { dir_name := *dist_dir + "/" + time.Now().Format("2006-01-02") file_name := dir_name + "/" + part.FileName() if err := os.Mkdir(dir_name, 0755); err != nil { if os.IsNotExist(err) { return err } } if fd, err := os.Open(file_name); err == nil { fd.Close() return nil } var err error var newfile *os.File if newfile, err = os.Create(file_name); err != nil { return err } log.Println("create", file_name) defer newfile.Close() buf := make([]byte, 1024*1024) for { n, err := part.Read(buf) newfile.Write(buf[:n]) if err == io.EOF { err = nil break } if err != nil { os.Remove(file_name) log.Print("remove", file_name) break } } return err }
func main() { var rr *http.Response var myreader multipart.Reader syscall.Umask(0000) if !parseME() { os.Exit(1) } var requesturl string requesturl = ("http://" + (*camera_ip) + ":" + strconv.Itoa(*camera_port) + "/mjpg/1/video.mjpg") fmt.Println("request sent to " + requesturl) rr, _, _ = http.Get(requesturl) myreader, _ = MultipartReader(rr) var p *multipart.Part var curr_length int = 0 var templen int var buff []byte var s string var m int var info *os.FileInfo var err os.Error info, err = os.Lstat(*save_folder) if err != nil { fmt.Println("Folder " + (*save_folder) + " Is problematic") fmt.Println(err.String()) os.Exit(1) } if !info.IsDirectory() { fmt.Println("Folder " + (*save_folder) + " Is not a directory") os.Exit(1) } var foldertime *time.Time = nil var foldersecs int64 var folderstamp string var tstamp_secs int64 var tstamp_nsecs int64 var msecs int64 var update bool var foldername string var imagename string var mywriter *os.File for i := 0; i < 1; { p, _ = myreader.NextPart() update = false tstamp_secs, tstamp_nsecs, _ = os.Time() if foldertime == nil { foldertime = time.SecondsToLocalTime(tstamp_secs) foldersecs = tstamp_secs update = true } else { if tstamp_secs > foldersecs { foldertime = time.SecondsToLocalTime(tstamp_secs) foldersecs = tstamp_secs update = true } } if update { folderstamp = strconv.Itoa64(foldertime.Year) + "_" + strconv.Itoa(foldertime.Month) + "_" + strconv.Itoa(foldertime.Day) + "_" + strconv.Itoa(foldertime.Hour) + "_" + strconv.Itoa(foldertime.Minute) + "_" + strconv.Itoa(foldertime.Second) foldername = (*save_folder) + "/" + (*camera_name) + "_" + folderstamp err = os.Mkdir(foldername, 0700) if err != nil { fmt.Fprintf(os.Stderr, "error creating %s because : %s\n", foldername, err.String()) os.Exit(1) } } templen, _ = strconv.Atoi(p.Header["Content-Length"]) if templen > curr_length { curr_length = templen buff = make([]byte, curr_length) } for counter := 0; counter < templen; { m, _ = p.Read(buff[counter:templen]) counter += m } p.Close() msecs = tstamp_nsecs / 1e6 imagename = "image_" + folderstamp + "_" + strconv.Itoa64(msecs) + ".jpg" s = foldername + "/" + imagename mywriter, err = os.Open(s, os.O_CREAT|os.O_WRONLY, 0600) if err != nil { fmt.Fprintf(os.Stderr, "error writing %d bytes because : %s\n", templen, err.String()) os.Exit(1) } for counter := 0; counter < templen; { m, _ = mywriter.Write(buff[counter:templen]) counter += m } } }
matches := boundaryRegexp.FindStringSubmatch(fakeResponseWriter.Header().Get("Content-Type")) Expect(matches).To(HaveLen(2)) Expect(matches[1]).NotTo(BeEmpty()) reader := multipart.NewReader(fakeResponseWriter.Body, matches[1]) partsCount := 0 var err error for err != io.EOF { var part *multipart.Part part, err = reader.NextPart() if err == io.EOF { break } partsCount++ data := make([]byte, 1024) n, _ := part.Read(data) Expect(data[0:n]).To(Equal([]byte("message"))) } Expect(partsCount).To(Equal(5)) close(done) }) It("sets the MIME type correctly", func() { close(messagesChan) r, err := http.NewRequest("GET", "", nil) Expect(err).ToNot(HaveOccurred()) handler.ServeHTTP(fakeResponseWriter, r) Expect(fakeResponseWriter.Header().Get("Content-Type")).To(MatchRegexp(`multipart/x-protobuf; boundary=`)) })