我有这个问题。我必须向 bmc API 上的端点提交(或不提交)文件。
带有
KEY:entry
的 VALUE:data_entry.txt
是要与值一起发送的 SON,与正文相同。
Attach-z2AF_WIAttachment1是我要提交的文件。我总是抛出一些错误,或者标头无效,或者文件类型无效,但在邮递员中正在工作。
我无法转换为 C#。 这是我到目前为止的代码:
try
{
//authentication
var dict = new Dictionary<string, string>();
dict.Add("username", "applicationUsernameJonDoe");
dict.Add("password", "applicationPassowrdXPTO");
var clientLogin = new HttpClient();
var req = new HttpRequestMessage(HttpMethod.Post, Endpoint_loginITSM) { Content = new FormUrlEncodedContent(dict) };
var res = clientLogin.SendAsync(req); //.Result.ToString();
var body = res.GetAwaiter().GetResult().Content.ReadAsStringAsync();
//pedido de criação de registo
using (var client = new HttpClient())
{
client.Timeout = TimeSpan.FromMinutes(10);
var request = new HttpRequestMessage
{
RequestUri = new Uri(Endpoint_CreateITSM),
Method = HttpMethod.Post
};
request.Headers.Add("Authorization", body.Result.ToString());
if (!string.IsNullOrEmpty(registos.Objeto.fileName))
{
registos.Objeto.Registo.z2AF_WIAttachment1 = registos.Objeto.fileName;
}
string json = JsonConvert.SerializeObject(new { values = registos.Objeto });
byte[] file_bytes = System.Convert.FromBase64String(registos.Objeto.fileEncoded);
MemoryStream memoryStream = new MemoryStream();
using (BsonDataWriter writer = new BsonDataWriter(memoryStream))
{
JsonSerializer serializer = new JsonSerializer();
serializer.Serialize(writer, registos.Objeto.Registo);
}
var data_entry_bytes = memoryStream.ToArray();
// we need to send a request with multipart/form-data
var multiForm = new MultipartFormDataContent();
ByteArrayContent data_entry_json_content = new ByteArrayContent(data_entry_bytes);
data_entry_json_content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
data_entry_json_content.Headers.ContentDisposition = new ContentDispositionHeaderValue("entry")
{
FileName = "data_entry.txt",
Name = "entry",
};
multiForm.Add(data_entry_json_content);
ByteArrayContent z2AF_WIAttachment1_content = new ByteArrayContent(file_bytes);
z2AF_WIAttachment1_content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
z2AF_WIAttachment1_content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attach-z2AF_WIAttachment1")
{
FileName = registos.Objeto.fileName,
Name = "attach-z2AF_WIAttachment1",
};
multiForm.Add(z2AF_WIAttachment1_content);
request.Content = multiForm;
var result = await client.SendAsync(request);
var resBody = result.Content.ReadAsStringAsync().Result.ToString();//.ConfigureAwait(false);
dynamic _resBody = JsonConvert.DeserializeObject<dynamic>(resBody);
string registoID = _resBody["values"].SysRequestID;
return ResponseHandler<string>.Resposta(false, "resposta api bit criar registos", registoID);
}
}
catch (Exception e)
{
string classname = this.GetType().Name;
CentralLibrary.Services.ErrorLoggingService.ErrorLogsForCore(classname, e, _env.WebRootPath);
return ResponseHandler<string>.Resposta(true, "EXCEPTION : resposta api bit criar registos", e.Message);
}
这是一个更好的解决方案。 我对最后一个有疑问,但对于那些不想使用 RestClient 库的人来说就是这样。但这是 100% 有效的,并且我有 NewtonSoft.Json 的 JsonProperty 名称,因此可以使用类似的名称
[JsonProperty("z1D Action")]
public string z1D_Action { get; } = "CREATE";
所以,我的代码是,并使用对象AbrirRegistosITSM和嵌套对象AbrirRegistosITSM_com_anexo我的最终解决方案是
AbrirRegistosITSM _registo = new AbrirRegistosITSM
{
Values = new AbrirRegistosITSM_com_anexo
{
Details = registos.Objeto.Comentario,
Customer_Login = registos.username,
Login_ID = registos.username,
SR_Type_Field_3 = registos.Objeto.Tipologia,
SR_Type_Field_28 = registos.Objeto.Categoria,
z2AF_WIAttachment1 = registos.Objeto.FicheiroNome
}
};
var client = new RestClient(Endpoint_CreateITSM);
string baseFolder = _env.WebRootPath;
string pathDir = Path.Combine(baseFolder, DateTime.Now.ToString().Replace('/', '_').Replace(' ', '_').Replace(':', '_'));
Directory.CreateDirectory(pathDir);
string pathDirFile = Path.Combine(pathDir, registos.Objeto.FicheiroNome);
File.WriteAllBytes(pathDirFile, Convert.FromBase64String(registos.Objeto.FicheiroBase64));
string pathEntryDir = Path.Combine(baseFolder, DateTime.Now.ToString().Replace('/', '_').Replace(' ', '_').Replace(':', '_'));
Directory.CreateDirectory(pathEntryDir);
string patnEntrydirFile = Path.Combine(pathEntryDir, "data_entry.txt");
File.WriteAllText(patnEntrydirFile, JsonConvert.SerializeObject(new { values = _registo.Values }));
var request = new RestRequest();
request.Method = Method.Post;
request.AddHeader("Authorization", token);
request.AddFile("entry", patnEntrydirFile, "application/json");
request.AddFile("attach-z2AF_WIAttachment1", pathDirFile, "application/octet-stream");
var reqbody = JsonConvert.SerializeObject(_registo);
request.AddParameter("application/json", reqbody, ParameterType.RequestBody);
RestResponse response = client.Execute(request);
var respostaBody = response.Content.ToString();//.ConfigureAwait(false);
dynamic _respostaBody = JsonConvert.DeserializeObject<dynamic>(respostaBody);
string _registoID = _respostaBody["values"]["Request Number"];
然后我返回我需要的请求号,但是那里有很多值。我使用 NewtonSoft 记住这一点。我不使用 JsonSerializer,因为我无法使用 JsonSerializer 保存带有空格的 json 属性名称。
我不完全确定这里出了什么问题。可能有很多事情,但我也许可以帮助你。在过去的几周里,我构建了一个 HttpClient,它将包含元数据的文件发送到 GraphQL 端点。
请确保以下事项: 我认为您正在通过电话请求该文件。请使用
Byte[]
将其存储在变量中作为 ReadAsByteArrayAsync()
。请注意对其进行解码或将其转换为字符串或其他内容。你只会损坏文件。
var response = client.GetAsync(fileUrl);
var downloadedFile = await response.Result.Content.ReadAsByteArrayAsync();
以下代码可能无法完全适合您的情况,但应该可以帮助您构建正确的请求,因为我还在请求中发送包含文件扩展名和其他一些信息的元数据。这很可能会将文件发送到您的 API,而不带文件扩展名。
using (var client = new HttpClient())
{
var file = new byte[] { 1, 2, 3 };
var fileToUpload = new ByteArrayContent(file);
var formData = new MultipartFormDataContent
{
{ fileToUpload, "entry", "passInFileExtensionForExample"},
{ fileToUpload, "attach-z2AF_WIAttachment1", "passInFileExtensionForExample" }
};
var response = await client.PostAsync("endpoint", formData);
}
使用以下代码添加承载令牌:
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
所以我找到了解决我的问题的方法。我将只提交一份文件。我还必须将 Json 正文作为文件提交 “entry”“data_entry.txt”,对于 HttpRequestMessage,您必须有一个内容
MultipartFormDataContent
,在这里您可以添加尽可能多的文件。我必须将 Json 主体转换为一个文件(在本例中我转换为二进制数组),其中包含名称条目和文件 data_entry.txt 的名称,但这是端点所需要的,所以......无论如何。
using (var client = new HttpClient())
{
client.Timeout = TimeSpan.FromMinutes(10);
MultipartFormDataContent content = new MultipartFormDataContent();
//adicionar ficheiro
byte[] file_bytes = System.Convert.FromBase64String(registos.Objeto.fileEncoded);
StreamContent fileContent = new StreamContent(new MemoryStream(file_bytes));
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "files[attach-z2AF_WIAttachment1]",
FileName = registos.Objeto.fileName
};
fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("application/octet-stream");
content.Add(fileContent);
//adicionar ficheiro entry
StreamContent entryStreamContent = new StreamContent(new MemoryStream(ObjectToByteArray(registos.Objeto.Registo)));
entryStreamContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "files[entry]",
FileName = "data_entry.txt"
};
entryStreamContent.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
content.Add(entryStreamContent);
var request = new HttpRequestMessage
{
RequestUri = new Uri(Endpoint_CreateITSM),
Method = HttpMethod.Post,
Content= content
};
request.Headers.Add("Authorization", body.Result.ToString());
string json = JsonConvert.SerializeObject(new { values = registos.Objeto.Registo});
request.Content = new ByteArrayContent(Encoding.UTF8.GetBytes(json));
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var resposta = await client.SendAsync(request);
var respostaBody = resposta.Content.ReadAsStringAsync().Result.ToString();//.ConfigureAwait(false);
dynamic _respostaBody = JsonConvert.DeserializeObject<dynamic>(respostaBody);
string _registoID = _respostaBody["values"].SysRequestID;
return ResponseHandler<string>.Resposta(false, "resposta api bit criar registos", _registoID);
这就是我的解决方案。它正在工作:)