JenSmith
JenSmith

Reputation: 11

Sending a C# multipart upload request to google drive

I am trying to create a multipart upload request from C# to upload a small file to Google Drive as per https://developers.google.com/drive/v3/web/multipart-upload

        using (var client = new HttpClient())
        {
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", access_token);

            //api endpoint
            var apiUri = new Uri("https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart");

            // read the image content 
            var imageBinaryContent = new ByteArrayContent(fileBytes);
            imageBinaryContent.Headers.Add("Content-Type", "image/jpeg");

            // prepare the metadata content
            string metaContent = "{\"name\":\"myObject\"}";
            byte[] byteArray = Encoding.UTF8.GetBytes(metaContent);
            var metaStream = new ByteArrayContent(byteArray);
            metaStream.Headers.Add("Content-Type", "application/json; charset=UTF-8");

            // create the multipartformdata content, set the headers, and add the above content
            var multipartContent = new MultipartFormDataContent();
            multipartContent.Headers.Remove("Content-Type");
            multipartContent.Headers.TryAddWithoutValidation("Content-Type", "multipart/form-data; boundry=myboundry---");
            multipartContent.Add(metaStream);
            multipartContent.Add(imageBinaryContent);


            HttpResponseMessage result = await client.PostAsync(apiUri, multipartContent);

        }

But I can't seem to get it working. This code works fine for simple uploads to Drive:

        using (var client = new HttpClient())
        {
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", access_token);

            //api endpoint
            var apiUri = new Uri("https://www.googleapis.com/upload/drive/v3/files?uploadType=media");


            // read the image content 
            var imageBinaryContent = new ByteArrayContent(fileBytes);
            imageBinaryContent.Headers.Add("Content-Type", "image/jpeg");


            HttpResponseMessage result = await client.PostAsync(apiUri, imageBinaryContent);

        }

Upvotes: 1

Views: 979

Answers (3)

ScriptKid
ScriptKid

Reputation: 1

I had the same problem and it was because of incorrect boundary separation between each form part.

Problem 1 : Misspelled / malformed boundary declaration in header:

Instead of using:

multipartContent.Headers.TryAddWithoutValidation("Content-Type", "multipart/form-data; boundry=myboundry---");

Do the following:

multipartContent.Headers.TryAddWithoutValidation("Content-Type", "multipart/related; boundary=myboundry");

Problem 2 : Missing MultipartFormDataContent part seperation:

Instead of using:

var multipartContent = new MultipartFormDataContent();
multipartContent.Add(metaStream);
multipartContent.Add(imageBinaryContent);

Do the following:

var multipartContent = new MultipartFormDataContent("myboundry");
multipartContent.Add(metaStream, "myboundry");
multipartContent.Add(imageBinaryContent, "myboundry");

Full version after fixes: (works for me when tested)

 using (var client = new HttpClient())
    {
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", access_token);

        //api endpoint
        var apiUri = new Uri("https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart");

        // read the image content 
        var imageBinaryContent = new ByteArrayContent(fileBytes);
        imageBinaryContent.Headers.Add("Content-Type", "image/jpeg");

        // prepare the metadata content
        string metaContent = "{\"name\":\"myObject\"}";
        byte[] byteArray = Encoding.UTF8.GetBytes(metaContent);
        var metaStream = new ByteArrayContent(byteArray);
        metaStream.Headers.Add("Content-Type", "application/json; charset=UTF-8");

        // create the multipartformdata content, set the headers, and add the above content
        var multipartContent = new MultipartFormDataContent("myboundry");
        multipartContent.Headers.Remove("Content-Type");
        multipartContent.Headers.TryAddWithoutValidation("Content-Type", "multipart/related; boundary=myboundry");
        multipartContent.Add(metaStream, "myboundry");
        multipartContent.Add(imageBinaryContent, "myboundry");

        HttpResponseMessage result = await client.PostAsync(apiUri, multipartContent);
    }

Upvotes: 0

Vincent
Vincent

Reputation: 1151

For those trying this out i .net core, here's my code:

public async Task UploadFile(Stream stream, string filename)
{
    var accessToken = "";

    using var client = _httpClientFactory.CreateClient();
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

    var metaContent = JsonContent.Create(new { name = filename });
    var streamContent = new StreamContent(stream);
    var multipart = new MultipartContent { metaContent, streamContent };
    streamContent.Headers.ContentType = new MediaTypeHeaderValue(MediaTypeNames.Application.Octet);
    streamContent.Headers.ContentLength = stream.Length;
    var result = await client.PostAsync("https://www.googleapis.com/upload/drive/v3/files?uploadtype=multipart", multipart);
}

Upvotes: 1

anu start
anu start

Reputation: 395

Two things jump out:

  1. You misspelled the word boundary in boundry=myboundry.
  2. Also make sure Content-Type is multipart/related.

Upvotes: 1

Related Questions