@@ -217,35 +217,39 @@ func (b *GoogleBackend) getValidToken(ctx context.Context) (string, error) {
217217 return b .token , nil
218218}
219219
220- func (b * GoogleBackend ) Upload (ctx context.Context , filename string , data [] byte ) error {
220+ func (b * GoogleBackend ) Upload (ctx context.Context , filename string , data io. Reader ) error {
221221 tok , err := b .getValidToken (ctx )
222222 if err != nil {
223223 return err
224224 }
225225
226- var metaBuf bytes. Buffer
227- metaWriter := multipart .NewWriter (& metaBuf )
226+ pr , pw := io . Pipe ()
227+ metaWriter := multipart .NewWriter (pw )
228228
229- // Part 1: Metadata
230- h := make (textproto.MIMEHeader )
231- h .Set ("Content-Type" , "application/json; charset=UTF-8" )
232- part1 , _ := metaWriter .CreatePart (h )
233- meta := map [string ]interface {}{
234- "name" : filename ,
235- }
236- if b .folderID != "" {
237- meta ["parents" ] = []string {b .folderID }
238- }
239- json .NewEncoder (part1 ).Encode (meta )
229+ go func () {
230+ defer pw .Close ()
231+ defer metaWriter .Close ()
232+
233+ // Part 1: Metadata
234+ h := make (textproto.MIMEHeader )
235+ h .Set ("Content-Type" , "application/json; charset=UTF-8" )
236+ part1 , _ := metaWriter .CreatePart (h )
237+ meta := map [string ]interface {}{
238+ "name" : filename ,
239+ }
240+ if b .folderID != "" {
241+ meta ["parents" ] = []string {b .folderID }
242+ }
243+ json .NewEncoder (part1 ).Encode (meta )
240244
241- // Part 2: Content
242- h = make (textproto.MIMEHeader )
243- h .Set ("Content-Type" , "application/octet-stream" )
244- part2 , _ := metaWriter .CreatePart (h )
245- part2 . Write ( data )
246- metaWriter . Close ()
245+ // Part 2: Content
246+ h = make (textproto.MIMEHeader )
247+ h .Set ("Content-Type" , "application/octet-stream" )
248+ part2 , _ := metaWriter .CreatePart (h )
249+ io . Copy ( part2 , data )
250+ } ()
247251
248- req , err := http .NewRequestWithContext (ctx , "POST" , "https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart" , & metaBuf )
252+ req , err := http .NewRequestWithContext (ctx , "POST" , "https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart" , pr )
249253 if err != nil {
250254 return err
251255 }
@@ -310,6 +314,11 @@ func (b *GoogleBackend) ListQuery(ctx context.Context, prefix string) ([]string,
310314 }
311315
312316 b .fileIdsMu .Lock ()
317+ // SAFETY: Prevent fileIDs map from infinite growth
318+ if len (b .fileIDs ) > 2000 {
319+ b .fileIDs = make (map [string ]string )
320+ }
321+
313322 var names []string
314323 for _ , f := range resData .Files {
315324 // Only collect exact prefix matches client-side just in case
@@ -323,7 +332,7 @@ func (b *GoogleBackend) ListQuery(ctx context.Context, prefix string) ([]string,
323332 return names , nil
324333}
325334
326- func (b * GoogleBackend ) Download (ctx context.Context , filename string ) ([] byte , error ) {
335+ func (b * GoogleBackend ) Download (ctx context.Context , filename string ) (io. ReadCloser , error ) {
327336 b .fileIdsMu .RLock ()
328337 fileID , ok := b .fileIDs [filename ]
329338 b .fileIdsMu .RUnlock ()
@@ -347,14 +356,14 @@ func (b *GoogleBackend) Download(ctx context.Context, filename string) ([]byte,
347356 if err != nil {
348357 return nil , err
349358 }
350- defer resp .Body .Close ()
351359
352360 if resp .StatusCode != http .StatusOK {
353361 body , _ := io .ReadAll (resp .Body )
362+ resp .Body .Close ()
354363 return nil , fmt .Errorf ("download returned %d: %s" , resp .StatusCode , string (body ))
355364 }
356365
357- return io . ReadAll ( resp .Body )
366+ return resp .Body , nil
358367}
359368
360369func (b * GoogleBackend ) Delete (ctx context.Context , filename string ) error {
0 commit comments