2

我正在尝试使用 gRPC 传输文件。我可以使用 gRPC 流发送数据,分成块。我正在寻找将文件名与数据一起传输的方法。我确定我缺少一个明显的解决方案。但这里有一些我能想到的方法

  1. 与每个块一起发送文件名,这是重传相同数据的明显缺点。.proto 文件看起来像
service KeyValueStore {
    rpc upload (stream FileData) returns (UploadStatus) {}
}

message FileData {
    string filename = 1;
    bytes data = 2;
}
  1. 将文件名作为第一个块发送。接收器需要知道这种编码。

但我正在寻找一个非hacky的解决方案。

我希望有一个像

service KeyValueStore {
    rpc upload (FileName, stream FileData) returns (UploadStatus) {}
}

但根据这里的回答,这是不可能的,也不鼓励

一般来说,有没有一种更简洁的方法来调用一个结合了普通参数和流参数的过程?或达到同样的效果?

4

1 回答 1

1

您链接的帖子是正确的。您的输入将是一个单独的协议缓冲区,一般来说,它应该被命名为“FooRequest”。响应对象也是如此,它应该被称为“FooResponse”之类的东西。将请求和响应对象与其内容解耦将为您提供空间以随着时间的推移以向后兼容的方式更改您的 API。

我们不支持多种请求类型这一事实在实践中并不是一个障碍,因为 protos 可以任意嵌套。考虑这样的 API。

message FileData {
    string filename = 1;
    bytes data = 2;
}

message UploadRequest {
    oneof payload {
        string filename = 1;
        FileData file_data = 2;
    }
}

service KeyValueStore {
    rpc upload (stream UploadRequest) returns (UploadResponse) {}
}

当然,从服务器的角度来看,行为不端的客户端现在可以在流的中间发送文件名。或者,相反,在不先发送文件名的情况下开始发送数据块。

您可以决定客户端必须发送文件名作为第一条消息。或者,只要在流结束之前发送文件名就可以了。或者,发送文件名可能完全是可选的,不发送文件名将导致文件名的默认值。

您对这些点的决定成为您 API 的一部分,但不会由 protobuf 作为 IDL 自动执行。您需要在服务器代码中明确处理这些极端情况。请记住,由于这些是 API 考虑因素,它们应该写在你的 protobuf 文件的某个地方。尽最大努力确保每条消息、RPC 和字段都有清晰简洁的文档字符串。

于 2019-11-13T19:52:18.290 回答