一日中、はまっていた。
画像と幾つかの変数を含む内容をRuby on rails 宛に、C#からHttpClientを使ってPOSTしたのだけど、うまくいかない。
素直にライブラリの使い方どおりやってもうまくいかない。
rails側で、変数名に改行が入る?という謎い事態になった。
回避法
content.Headers.Add("Content-Disposition", $"form-data; name=\"{item.Key}\"");
というように、ここでnameを指定し、MultipartFormDataContentにAddする時、名前をつけない。
根本的な解決法という感じはしないけど。
ソースコード全体
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
namespace Test
{
public class ImagePostData
{
public string id { get; set; }
public string kind { get; set; }
public byte[] image { get; set; }
//本来は変数はたくさんあったので、メタプログラミング用
IEnumerable<KeyValuePair<string, string>> GetProperties()
{
foreach (var item in this.GetType().GetProperties())
{
if (item.PropertyType != typeof(byte[]))
{
yield return new KeyValuePair<string, string>(item.Name, item.GetValue(this).ToString());
}
}
}
public MultipartFormDataContent CreateMultipartFormDataContent()
{
var dataContent = new System.Net.Http.MultipartFormDataContent();
var byteContent = new ByteArrayContent(image);
//Content-Dispositionの指定と、nameを文字列で渡す。
byteContent.Headers.Add("Content-Disposition", $"form-data; name=\"image\" ; filename = \"{this.id}_{this.kind}.jpg\"");
byteContent.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
//nameをつけずに渡す。
dataContent.Add(byteContent);
foreach (var item in GetProperties())
{
var content = new StringContent(item.Value);
//nameをヘッダーにかく
content.Headers.Add("Content-Disposition", $"form-data; name=\"{item.Key}\"");
//nameをつけずに渡す。
dataContent.Add(content);
}
return dataContent;
}
}
[TestClass]
public class UnitTest2
{
string postUrl = "https://****.****.com/****/upload";
/// <summary>
/// 使い方
/// </summary>
/// <returns></returns>
[TestMethod]
public async Task TestMethod1()
{
System.Net.Http.HttpClient client = new System.Net.Http.HttpClient();
var imageFile = @"0.jpeg";
var post = new ImagePostData()
{
image = System.IO.File.ReadAllBytes(imageFile),
id = "1",
kind = "default",
};
var c = post.CreateMultipartFormDataContent();
var result = await client.PostAsync(postUrl, c);
}
}
}