Upload video on Twitter without 3rd library - c#

I use Hammock in the project and I want to upload videos to Twitter. I also get the "media type unrecognized" error when I try with the following code. Where part am I doing wrong?
var restClient = new Hammock.RestClient
{
Authority = "https://upload.twitter.com",
Encoding = Encoding.UTF8,
};
var restRequest = new Hammock.RestRequest
{
Credentials = credentials,
Path = "/1.1/media/upload.json",
Method = Hammock.Web.WebMethod.Post,
Encoding = Encoding.UTF8,
};
Stream stream = new MemoryStream(images);
restRequest.AddFile("media", "test", stream);
var asyncResult = restClient.BeginRequest(restRequest);
var response = restClient.EndRequest(asyncResult);
var jsonData = JsonConvert.DeserializeObject<Image>(response.Content);

Related

How to CREATE POST IN C# to an endpoint on BMC REMEDY API to create a ticket with files submited in form-data?

I have this problem. i have to submit a file (or not) to an endpoint on an API of bmc.
the KEY:entry with the VALUE:data_entry.txt is the json to send with the values, as the same of the body.
The attach-z2AF_WIAttachment1 is the file i want to submit. I'm it's always throuwing some error, or headers invalid, or filetype not valid, but in postman is working.
I cant convert to C#.
this is my code so far, or now.
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);
}
Here is a better solution.
I had a problem with the last, but for someone who doesnt wnat to use de library RestClient that's the way. But this is working 100% and i have JsonProperty Names for NewtonSoft.Json so this workin with names like
[JsonProperty("z1D Action")]
public string z1D_Action { get; } = "CREATE";
so, my code is, and using an object AbrirRegistosITSM with nested object AbrirRegistosITSM_com_anexo my final solution is
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"];
then i return the request number that what i need, but you have a lot of values there. I use NewtonSoft remember that. I dont use JsonSerializer because i wasn't able to save the json property names with spaces with JsonSerializer.
I'm not entirely sure what's going wrong here. It can be a lot of things, but I might be able to get you going. The last couple of weeks I build a HttpClient that sends a file with metadata to a GraphQL endpoint.
Please ensure the following:
I think you are requesting the file through an call. Please store it in a variable as a Byte[] using the ReadAsByteArrayAsync(). Do note decode it or cast it to a string or anything. You'll just corrupt the file.
var response = client.GetAsync(fileUrl);
var downloadedFile = await response.Result.Content.ReadAsByteArrayAsync();
The following code might not work entirely in your case, but should help you get going building the right request, since I'm also sending metadata in my request containing the file extension and some other information. This will most likely send the file to your API without a file extension.
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);
}
Add the Bearer token using the following code:
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
So i've discover the solution for my problem. I'm gonna to submit only one file. I have to submit also the Json body as a file "entry" "data_entry.txt" and for HttpRequestMessage you have to have a content MultipartFormDataContent and here you can add as many files as you have. i have to convert the Json body to a file ( in this case i converted to binary Array) with the name entry, and the name of the file data_entry.txt, but it's what the endpoint needs, so...whatever.
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);
So this is my solution. and it's working :)

YouTube API Video Upload: BadRequest: Metadata part is too large

I am uploading a video to YouTube via their API with C#. I am using HttpClient.PostAsync() for that.
I get the following error after executing PostAsync(): Bad Request: Metadata part is too large.
I am not quite sure, if this error was generated by my code, or if the error happened on the YouTube API.
//Prepare the file from the form
var filePath = Path.GetTempFileName();
if (formFile.Length > 0)
{
using (var stream = new FileStream(filePath, FileMode.Create))
{
await formFile.CopyToAsync(stream);
}
}
//Application logic, not related to YouTube API
var user = await _userManager.FindByIdAsync(User.GetClaim(OpenIdConnectConstants.Claims.Subject));
var personalPot = await _context.PersonalPots.FirstOrDefaultAsync(i => i.Id == id);
if (user.Id != personalPot.Owner.Id)
{
return Unauthorized();
}
//Get the access token for the YouTube API
var accessToken = await _externalContentService.RefreshGoogleToken(personalPot.Id, new Guid(user.Id));
//Construct the properties, which will be send with the video file to upload
var properties = new Properties()
{
snippet = new Snippet()
{
title = title,
categoryId = categoryId,
defaultLanguage = defaultLanguage,
description = description,
tags = tags.Split(",")
},
status = new Status()
{
embeddable = embeddable == "true",
license = license,
privacyStatus = privacy,
publicStatsViewable = publicStatsViewable == "true"
}
};
//Construct the HttpClient to post the file to YouTube
var client = new HttpClient
{
BaseAddress = new Uri("https://www.googleapis.com/"),
Timeout = new TimeSpan(0, 0, 0, 0, Timeout.Infinite),
MaxResponseContentBufferSize = 2147483647
};
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {accessToken}");
var requestContent = new MultipartFormDataContent();
var fileContent = new StreamContent(formFile.OpenReadStream());
var stringContent = new StringContent(JsonConvert.SerializeObject(properties), Encoding.UTF8, "application/json");
requestContent.Add(fileContent);
requestContent.Add(stringContent);
var result = await client.PostAsync("upload/youtube/v3/videos?part=snippet,status", requestContent);
//Result content will be "Bad Request; Metadata part too large"
if (!result.IsSuccessStatusCode)
{
return BadRequest(new {content = result.Content.ReadAsStringAsync(), reasonPhrase = result.ReasonPhrase});
}

Cannot download a pdf with RestSharp?

I have been struggling to download a simple pdf hosted online using restsharp. I have been playing around with the code for over an hour and all I get are null object results.
The file downloads easily in POSTMAN using a GET and no content header set but still what gives?
Below is the noddy sandbox test I have been experimenting around with:
[TestFixture]
public class Sandbox
{
[Test]
public void Test()
{
var uri = "https://www.nlm.nih.gov/mesh/2018/download/2018NewMeShHeadings.pdf";
var client = new RestClient();
var request = new RestRequest(uri, Method.GET);
//request.AddHeader("Content-Type", "application/octet-stream");
byte[] response = client.DownloadData(request);
File.WriteAllBytes(#"C:\temp\1.pdf", response);
}
}
Update: Return a Stream
var baseUri = "https://www.nlm.nih.gov/mesh/2018/download/";
var client = new RestClient(baseUri);
var request = new RestRequest("2018NewMeShHeadings.pdf", Method.GET);
request.AddHeader("Content-Type", "application/octet-stream");
var tempFile = Path.GetTempFileName();
var stream = File.Create(tempFile, 1024, FileOptions.DeleteOnClose);
request.ResponseWriter = responseStream => responseStream.CopyTo(stream);
var response = client.DownloadData(request);
The stream is now populated with the downloaded data.
Try this:
var uri = "https://www.nlm.nih.gov/mesh/2018/download/";
var client = new RestClient(uri);
var request = new RestRequest("2018NewMeShHeadings.pdf", Method.GET);
//request.AddHeader("Content-Type", "application/octet-stream");
byte[] response = client.DownloadData(request);

Getting unauthorised access in YouTube API [Xamarin.Forms (Portable)]

I am trying to upload the Video from Xamarin.Forms (Portable) to YouTube, I have tried to use the Google APIs but the Google APIs are not compatible with the Xamarin.Forms (Portable) at this stage. So, I compulsory have to upload it via HttpClient but I am getting Unauthorised in StatusCode
public async Task UploadVideoAsync(Stream stream)
{
//var token = flow.LoadTokenAsync("", CancellationToken.None).Result;
string json = #"{
""snippet"": {
""title"": ""using API"",
""description"": ""This is a description of my video"",
""tags"": [""cool"", ""video"", ""more keywords""],
""categoryId"": ""21"",
},
""status"": {
""privacyStatus"": ""public"",
""embeddable"": true,
""license"": ""youtube""
}
}";
var JsonReqMsg = new StringContent(json);
JsonReqMsg.Headers.ContentType = new MediaTypeHeaderValue("application/json")
{
CharSet = "UTF-8"
};
var request = new HttpRequestMessage
(HttpMethod.Post, new Uri("https://www.googleapis.com/upload/youtube/v3/videos?uploadType=resumable&part=snippet,status"));
request.Headers.Add("X-Upload-Content-Length", stream.Length.ToString());
request.Headers.Add("x-upload-content-type", "video/*");
request.Content = JsonReqMsg;
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Add("Authorization", Constants.API.Google.AccessTokenType + " " + Constants.API.Google.AccessToken);
var UploadReq = await httpClient.SendAsync(request);
if (UploadReq.IsSuccessStatusCode)
{
IEnumerable<string> _VideoUrl = null;
var res = await UploadReq.Content.ReadAsStringAsync();
UploadReq.Headers.TryGetValues("Location", out _VideoUrl);
var binaryContent = new StreamContent(stream);
var UploadReq_ = await httpClient.PutAsync(new Uri(_VideoUrl.ToString()), binaryContent);
if (UploadReq_.IsSuccessStatusCode)
{
var res_ = await UploadReq_.Content.ReadAsStringAsync();
}
}
}
Is there anything wrong in the code?
You're authorization is incorrect. You should be using "bearer" or a developer key. Here is the YouTube documentation: https://developers.google.com/youtube/2.0/developers_guide_protocol#OAuth2_Calling_a_Google_API

C# Add item to Sharepoint list using REST API

I would like to add an item to a list in sharepoint using below code:
protected string httpGetPost(string getPostMode, string url, string dataToPost = "")
{
HttpWebRequest endpointRequest = (HttpWebRequest)WebRequest.Create(url);
endpointRequest.Method = getPostMode;
var credentialCache = new CredentialCache();
credentialCache.Add(
new Uri(endpointRequest.RequestUri.GetLeftPart(UriPartial.Authority)), // request url's host
"Digest", // authentication type
new NetworkCredential(userName, password) // credentials
);
endpointRequest.Credentials = credentialCache;
endpointRequest.Accept = "application/json;odata=verbose";
endpointRequest.ContentType = "application/json;odata=verbose";
if (!string.IsNullOrEmpty(dataToPost))
{
using (Stream dataStream = endpointRequest.GetRequestStream())
{
byte[] bs = Encoding.ASCII.GetBytes(dataToPost);
dataStream.Write(bs, 0, bs.Length);
}
}
using (var resp = endpointRequest.GetResponse())
{
var html = new StreamReader(resp.GetResponseStream()).ReadToEnd();
return html;
}
}
And call the above method using below code:
httpGetPost("POST", url, "{\"__metadata\": { \"type\": \"SP.Data.Test_x0020_ListListItem\" }, \"Title\": \"Test\", \"Column B\", \"BBB\"}");
Here's the data I'm posting:
{"__metadata": { "type": "SP.Data.Test_x0020_ListListItem" }, "Title":
"Test", "Column B", "BBB"}
I've took a look at this website https://msdn.microsoft.com/en-us/library/office/dn292552.aspx, but the authorization is different, it's using an accesstoken, but here's the problem:
In this website: http://sharepoint.stackexchange.com/questions/69617/sharepoint-2013-oauth-url-to-get-token, it saids I can't get the accesstoken, so I used username and password to login the sharepoint, but here comes another problem:
A System.Net.WebException is thrown in var resp = endpointRequest.GetResponse(), the error is saying The remote server returned an error: (403) Forbidden.
The account is a domain admin as well as a sharepoint admin.
Why I'm still getting the 403 error?
For some reasons, I can only use the REST API to communicate with sharepoint.
Here is a slightly different method to achieve your goals. Some of the objects are specific to Store Apps in this example, but they can all easily be replaced with other values in a standard app.
public string digest()
{
String retVal = "";
try
{
string url = "https://YourSite.com/";
HttpClient client = new HttpClient(new HttpClientHandler() { UseDefaultCredentials = true });
client.BaseAddress = new System.Uri(url);
string cmd = "_api/contextinfo";
client.DefaultRequestHeaders.Add("Accept", "application/json;odata=verbose");
client.DefaultRequestHeaders.Add("ContentType", "application/json");
client.DefaultRequestHeaders.Add("ContentLength", "0");
StringContent httpContent = new StringContent("");
var response = client.PostAsync(cmd, httpContent).Result;
if (response.IsSuccessStatusCode)
{
string content = response.Content.ReadAsStringAsync().Result;
JsonObject val = JsonValue.Parse(content).GetObject();
JsonObject d = val.GetNamedObject("d");
JsonObject wi = d.GetNamedObject("GetContextWebInformation");
retVal = wi.GetNamedString("FormDigestValue");
}
}
catch
{ }
return retVal;
}
FileOpenPicker picker = new FileOpenPicker();
picker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
picker.ViewMode = PickerViewMode.Thumbnail;
// Filter to include a sample subset of file types.
picker.FileTypeFilter.Clear();
picker.FileTypeFilter.Add(".bmp");
picker.FileTypeFilter.Add(".png");
picker.FileTypeFilter.Add(".jpeg");
picker.FileTypeFilter.Add(".jpg");
// Open the file picker.
StorageFile path = await picker.PickSingleFileAsync();
if (path != null)
{
string url = "https://YourSite.com/Subsite/";
HttpClient client = new HttpClient(new HttpClientHandler() { UseDefaultCredentials = true });
client.BaseAddress = new System.Uri(url);
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Add("Accept", "application/json;odata=verbose");
client.DefaultRequestHeaders.Add("X-RequestDigest", digest());
client.DefaultRequestHeaders.Add("X-HTTP-Method", "POST");
client.DefaultRequestHeaders.Add("binaryStringRequestBody", "true");
IRandomAccessStream fileStream = await path.OpenAsync(FileAccessMode.Read);
var reader = new DataReader(fileStream.GetInputStreamAt(0));
await reader.LoadAsync((uint)fileStream.Size);
Byte[] content = new byte[fileStream.Size];
reader.ReadBytes(content);
ByteArrayContent file = new ByteArrayContent(content);
HttpResponseMessage response = await client.PostAsync("_api/web/lists/getByTitle(#TargetLibrary)/RootFolder/Files/add(url=#TargetFileName,overwrite='true')?#TargetLibrary='Project Photos'&#TargetFileName='TestUpload.jpg'", file);
response.EnsureSuccessStatusCode();
if (response.IsSuccessStatusCode)
{ }
}

Categories