Uploading Files using gRPC and C#

Uploading Files using gRPC and C#

In the world of modern software development, communication between services is crucial. While RESTful APIs have been the go-to choice for many years, gRPC is gaining traction for its efficiency, performance, and versatility. In this blog post, we’ll explore how to upload files using gRPC and C# – a powerful combination that can help streamline file transfer in your applications.

Before we proceed, let’s first take a look at an article that guides you through creating a gRPC application in .NET Core

Create a gRPC client and server in ASP.NET Core
Create a gRPC client and server in ASP.NET Core-Client

Understanding gRPC and File Upload

gRPC is a remote procedure call (RPC) framework developed by Google. It uses the Protocol Buffers (Protobuf) format for data serialization, providing a lightweight, efficient, and language-agnostic way to communicate between services. One of the unique features of gRPC is its support for streaming, which makes it an ideal choice for handling large files like images, videos, and documents.

Setting Up the Environment

Before we dive into the code, let’s ensure you have the necessary tools set up. Make sure you have the .NET SDK installed and a basic understanding of C#.

Defining the Protobuf Messages

In your gRPC service definition (file.proto file), you define the messages and services that your application will use. In our case, we have a service called FileService that includes an UploadFile method. The FileChunk message represents a chunk of the file to be uploaded, and the FileUploadStatus message reports the upload progress.

Here’s the file.proto file:

GrpcFileService\Protos\file.proto

syntax = "proto3";

service FileService {
    rpc UploadFile (stream FileChunk) returns (FileUploadStatus);
}

message FileChunk {
    bytes chunk_data = 1;
}

message FileUploadStatus {
    int32 percentage_complete = 1;
    bool is_complete = 2;
}

Server-Side Implementation:

On the server side, you’ll need to set up your gRPC service using the .MapGrpcService method. This maps your defined FileService to a gRPC endpoint. This service is responsible for processing incoming file chunks and reporting the upload progress.

Here’s the server-side code:

GrpcFileService\Program.cs

using GrpcFileService.Services;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddGrpc();

var app = builder.Build();

app.MapGrpcService<FileService>();

app.Run();

Client-Side Implementation

The client application sends the file in chunks to the server using the generated client code. In the client application, you establish a connection with the gRPC service using the GrpcChannel and create an instance of the FileServiceClient. You then read the file in chunks, convert each chunk to a FileChunk message, and send it to the server using the UploadFile method. After sending all chunks, you signal the completion of the stream and await the server’s response.

Here’s the client-side code:

GrpcClient\Program.cs

using Grpc.Net.Client;
using GrpcFileService;

public class Program
{
    static async Task Main(string[] args)
    {
        await UploadAsync();
    }

    public static async Task UploadAsync()
    {
        using var channel = GrpcChannel.ForAddress("https://localhost:7108");
        var client = new FileService.FileServiceClient(channel);

        using var requestStream = client.UploadFile();

        const int chunkSize = 8192;
        byte[] fileData = File.ReadAllBytes("c:\\temp\\ReadMe.pdf");
        int totalChunks = (int)Math.Ceiling((double)fileData.Length / chunkSize);

        for (int chunkIndex = 0; chunkIndex < totalChunks; chunkIndex++)
        {
            int startIndex = chunkIndex * chunkSize;
            int chunkLength = Math.Min(chunkSize, fileData.Length - startIndex);
            byte[] chunk = new byte[chunkLength];
            Array.Copy(fileData, startIndex, chunk, 0, chunkLength);

            await requestStream.RequestStream.WriteAsync(new FileChunk { ChunkData = ByteString.CopyFrom(chunk) });
        }

        await requestStream.RequestStream.CompleteAsync();

        var finalResponse = await requestStream.ResponseAsync;
        Console.WriteLine($"Upload Complete. Status: {finalResponse.IsComplete}");
    }
}

Make sure that you have added the file.proto in GrpcClient.csproj

 <ItemGroup>
   <Protobuf Include="..\GrpcFileService\Protos\file.proto" GrpcServices="Client">
     <Link>Protos\file.proto</Link>
   </Protobuf>
 </ItemGroup>

Conclusion

By utilizing gRPC and C#, you can significantly improve the efficiency and speed of uploading files in your applications. The combination of gRPC’s streaming capabilities and C#'s robustness allows for seamless communication between clients and servers. This blog post has provided a basic overview of uploading files using gRPC and C#, and you can expand upon this foundation to create more sophisticated file transfer mechanisms.

Remember that this is just a starting point. As you continue your journey with gRPC and C#, you can explore features like error handling, security, and optimizing performance for different types of file uploads.

Additional Resources:

  1. Official gRPC Documentation
  2. gRPC C# Quick Start
  3. Protocol Buffers Documentation
Next Post Previous Post
No Comment
Add Comment
comment url