Download sends the file at the temp download location to the client
(stream remote.Downstream_DownloadServer)
| 147 | |
| 148 | // Download sends the file at the temp download location to the client |
| 149 | func (d *Downstream) Download(stream remote.Downstream_DownloadServer) error { |
| 150 | filesToCompress := make([]string, 0, 128) |
| 151 | for { |
| 152 | paths, err := stream.Recv() |
| 153 | if paths != nil { |
| 154 | filesToCompress = append(filesToCompress, paths.Paths...) |
| 155 | } |
| 156 | |
| 157 | if err == io.EOF { |
| 158 | break |
| 159 | } |
| 160 | if err != nil { |
| 161 | return err |
| 162 | } |
| 163 | } |
| 164 | |
| 165 | // Create os pipe |
| 166 | reader, writer := io.Pipe() |
| 167 | |
| 168 | // Compress archive and send at the same time |
| 169 | errorChan := make(chan error) |
| 170 | go func() { |
| 171 | errorChan <- d.compress(writer, filesToCompress) |
| 172 | }() |
| 173 | |
| 174 | // Send compressed archive to client |
| 175 | buf := make([]byte, 16*1024) |
| 176 | for { |
| 177 | n, err := reader.Read(buf) |
| 178 | if n > 0 { |
| 179 | err := stream.Send(&remote.Chunk{ |
| 180 | Content: buf[:n], |
| 181 | }) |
| 182 | if err != nil { |
| 183 | return errors.Wrap(err, "stream send") |
| 184 | } |
| 185 | } |
| 186 | |
| 187 | if err == io.EOF { |
| 188 | break |
| 189 | } else if err != nil { |
| 190 | return errors.Wrap(err, "read file") |
| 191 | } |
| 192 | } |
| 193 | |
| 194 | reader.Close() |
| 195 | return <-errorChan |
| 196 | } |
| 197 | |
| 198 | // Compress compresses the given files and folders into a tar archive |
| 199 | func (d *Downstream) compress(writer io.WriteCloser, files []string) error { |