関連

https://www.notion.so/Flutter-x-golang-x-gRPC-f299ddde01bf48bc87ed07d2f4396061

アップロードよりも単純。gRPC ばんざい

schema

service PlayerService {
  rpc Download (DownloadRequest) returns (stream DownloadResponse) {}
}

message DownloadRequest {
  int64 audio_id = 1;
}

message DownloadResponse {
  util.File file = 1;
}

server

func (a *PlayerAdapter) Download(r *playerpb.DownloadRequest, stream playerpb.PlayerService_DownloadServer) error {
	ctx := stream.Context()

	audio, err := a.audioUC.Get(ctx, r.AudioId)
	if err != nil {
		return err
	}
	f, err := os.Open(audio.Path)
	if err != nil {
		return err
	}
	defer f.Close()

  // バイト単位で分割してストリーミング(要調整)
	var b [4096 * 1000]byte
	for {
		n, err := f.Read(b[:])
		if err != nil {
			if err != io.EOF {
				return err
			}
			break
		}
		err = stream.Send(&playerpb.DownloadResponse{
			File: &utilpb.File{
				Content: b[:n],
			},
		})
		if err != nil {
			return err
		}
	}

	util.LoggingInfo(ctx, "PlayerAdapter.Download end", logrus.Fields{
		"r.AudioId": r.AudioId,
	})

	return nil
}

client

@override
  Future<Uint8List> download(int id) async {
    final channel = createChannel();
    final stub = _createStub(channel);

    final request = $pbgrpc.DownloadRequest()
      ..audioId = $fixnum.Int64(id);

    var results = <int>[];

    // 結果を全て待つ場合, await for で
    await for (final reply in stub.download(request)) {
      results = [...results, ...reply.file.content];
    }

    return Uint8List.fromList(results);
  }