Vimeo API C# - Uploading a video - vimeo-api

I'm following the api's guide about resumable uploads.
I managed to get a response after step 1 ("create the video"),
with a uri and a upload_link.
About the second part, things are not as clear.
It only says which headers should I sent, but there are two things I don't get,
first - where do I need to put the "upload_link"?
Should the call be like this:
/me/{upload_link}? (of course im also adding the access token, etc)
second, what about the actual file? I guess i should send it in the same method, but how? No word about it.
This is the code for the PATCH request:
public string UploadPatch(
string uploadlink,
string method)
{
var headers = new WebHeaderCollection()
{
{ "Tus-Resumable", "1.0.0" },
{ "Upload-Offest", "0" }
};
method = method.ToUpper();
string body = "";
string contentType = "application/offset+octet-stream";
return Helpers.HTTPUpload(uploadlink, method, headers, body, contentType);
}
And HTTPUpload():
public static string HTTPPatch(string url, string method,
WebHeaderCollection headers, string payload,
string contentType)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.CreateHttp(url);
if (Proxy != null) request.Proxy = Proxy;
request.Headers = headers;
request.Method = method;
request.Accept = "application/vnd.vimeo.*+json; version=3.1";
request.ContentType = contentType;
request.KeepAlive = false;
if (!String.IsNullOrWhiteSpace(payload))
{
var streamBytes = Helpers.ToByteArray(payload);
request.ContentLength = streamBytes.Length;
Stream reqStream = request.GetRequestStream();
reqStream.Write(streamBytes, 0, streamBytes.Length);
reqStream.Close();
}
HttpWebResponse response = (HttpWebResponse)(request.GetResponse());
Debug.WriteLine(((HttpWebResponse)response).StatusDescription);
var dataStream = response.GetResponseStream();
StreamReader reader = new StreamReader(dataStream);
string responseFromServer = reader.ReadToEnd();
reader.Close();
dataStream.Close();
response.Close();
Debug.WriteLine(String.Format("Response from URL {0}:", url), "HTTPFetch");
Debug.WriteLine(responseFromServer, "HTTPFetch");
return responseFromServer;
}
Thanks

The upload_link is the URL where you upload the video to. In other words, make your call to the https://[...].cloud.vimeo.com/upload?[...] URL instead of the https://api.vimeo.com host that is used for other API requests.
Additionally, when you make a request to that cloud.vimeo.com upload_link, only provide the required headers as specified in the documentation.
https://developer.vimeo.com/api/upload/videos#resumable-approach

The code is VB.Net, but you can change to C#
'Imports / use these classes
'Imports System.Net
'Imports Newtonsoft.Json
'Imports System.IO
Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Try
'Receive the video from File Upload
If Not IsNothing(fuVideo.PostedFile) Then
'You will need this for SSL
System.Net.ServicePointManager.SecurityProtocol = (SecurityProtocolType.Tls Or (SecurityProtocolType.Tls11 Or SecurityProtocolType.Tls12))
'Path to save the video Save
Dim vFilePath As String = Server.MapPath("App_data/Videos")
Dim vFileNameAndPath As String = vFilePath & "/" & fuVideo.PostedFile.FileName
'Save Video
fuVideo.PostedFile.SaveAs(vFileNameAndPath)
'Get the size
Dim vSize As String = New FileInfo(vFileNameAndPath).Length()
'Vimeo URL
Dim vVimeURL As String = "https://api.vimeo.com/me/videos"
Dim wc As WebClient = New WebClient()
wc.Headers.Clear()
wc.Headers.Add("Authorization", "bearer XXXXXXXXXXXXXXXXX") 'Use your App Code
wc.Headers.Add("Content-Type", "application/json")
wc.Headers.Add("Accept", "application/vnd.vimeo.*+json;version=3.4")
wc.Encoding = System.Text.Encoding.UTF8
'txtName is a text box, so you can give a Title to the Video
Dim vData As String = "{ ""upload"": {""approach"": ""tus"",""size"": """ & vSize & """ }, ""name"" : """ & txtName.Text & """ }"
Dim vimeoTicket = JsonConvert.DeserializeObject(wc.UploadString(vVimeURL, "POST", vData))
wc.Headers.Clear()
wc.Headers.Add("Content-Type", "application/offset+octet-stream")
wc.Headers.Add("Accept", "application/vnd.vimeo.*+json;version=3.4")
wc.Headers.Add("Tus-Resumable", "1.0.0")
wc.Headers.Add("Upload-Offset", "0")
Dim vupload_link As String = vimeoTicket("upload")("upload_link").Value 'Json from Vimeo has the upload_link
Dim vResponse As Byte() = wc.UploadFile(vupload_link, "PATCH", vFileNameAndPath)
Response.Write(System.Text.Encoding.Unicode.GetString(vResponse)) ' If everething is ok, vResponse is Nothing
End If
Catch ex As Exception
ltrErro.Text = "Error"
End Try
End Sub

for this may look at the sample code below:-
I am using a nuget library vimeo-dot-net also at https://github.com/mfilippov/vimeo-dot-net, this has a wrapper built around upload, delete etc.
public ActionResult UploadChapterVideoVimeo(HttpPostedFileBase file, string productID = "")
{
if (file != null){
var authCheck = Task.Run(async () => await vimeoClient.GetAccountInformationAsync()).Result;
if (authCheck.Name != null)
{
BinaryContent binaryContent = new BinaryContent(file.InputStream, file.ContentType);
int chunkSize = 0;
int contenetLength = file.ContentLength;
int temp1 = contenetLength / 1024;
if (temp1 > 1)
{
chunkSize = temp1 / 1024;
chunkSize = chunkSize * 1048576;
}
else
{ chunkSize = chunkSize * 1048576; }
binaryContent.OriginalFileName = file.FileName;
var d = Task.Run(async () => await vimeoClient.UploadEntireFileAsync(binaryContent, chunkSize, null)).Result;
vmodel.chapter_vimeo_url = "VIMEO-" + d.ClipUri;
}
return RedirectToAction("ProductBuilder", "Products", new { productId = EncryptedProductID, message = "Successfully Uploaded video", type = 1 });
}
}
catch (Exception exc)
{
return RedirectToAction("ProductBuilder", "Products", new { productId = EncryptedProductID, message = "Failed to Uploaded video " + exc.Message, type = 0 });
}
}
return null; }

Related

AWS signature V4 API call

Hi everyone New to cosing and I am getting Hashed Signature wrong, Can anyone help me with Dumbed down version of AWS V4 API signature,
Thanks a Million
//Script start
def execute() {
def accountPropertyService = services.getAccountPropertyService()
// List<String> entityUrls = context.getStringListVariable("entityUrls")
def sessionAccessKey = context.getStringVariable("sessionAccessKey")
def sessionSecretKey = context.getStringVariable("sessionSecretKey")
def sessionExpiry = context.getStringVariable("sessionExpiry")
def sessionToken = context.getStringVariable("sessionToken")
def apiClientKey = accountPropertyService.getAccountProperty("rl-api-clientKey").getValue()
//Generate signature & Timestamp
def date = new Date()
Calendar c = Calendar.getInstance()
c.add(Calendar.MINUTE, 5)
SimpleDateFormat formatDate = new SimpleDateFormat("yyyyMMdd")
SimpleDateFormat formatAmzDate = new SimpleDateFormat("yyyyMMdd'T'HHmmss'Z'")
def dateString = formatDate.format(date)
def amzDateTime = formatAmzDate.format(c.getTime())
def signature = getSignatureKey(sessionAccessKey, dateString, "us-east-1", "execute-api")
def signatureString = convertbyte(signature)
context.logInfo("Signature : $signatureString")
context.logInfo("AMZ Date : $amzDateTime")
Unirest.setTimeouts(0, 0)
HttpResponse<String> response = Unirest.get("https://api-staging.rightsline.com/v4/XXXX-item/42262XX")
.header("x-api-key", apiClientKey)
.header("X-Amz-Security-Token", sessionToken)
.header("X-Amz-Date", amzDateTime)
.header("Authorization", "AWS4-HMAC-SHA256 Credential=$sessionAccessKey/20230118/us-east-1/execute-api/aws4_request, SignedHeaders=host;x-amz-date;x-amz-security-token;x-api-key, Signature=$signatureString")
.asString()
context.logInfo("AWS4-HMAC-SHA256 Credential=$sessionAccessKey/20230118/us-east-1/execute-api/aws4_request, SignedHeaders=host;x-amz-date;x-amz-security-token;x-api-key, Signature=$signatureString\"")
//Get & Parse response
def responseCode = response.getStatus()
def responseBody = response.getBody()
context.logInfo("Response Code : $responseCode")
context.logInfo("Response Body : $responseBody")
if (responseCode > 299) {
throw new Exception("Unexpected response code : $responseCode")
} else {
def responseJson = new JsonSlurper().parseText(responseBody)
}
//return "process"
// }
} else {
context.logInfo("No entity urls to process")
//return "done"
}
static byte[] HmacSHA256(String data, byte[] key) throws Exception {
String algorithm = "HmacSHA256"
Mac mac = Mac.getInstance(algorithm)
mac.init(new SecretKeySpec(key, algorithm))
return mac.doFinal(data.getBytes("UTF-8"))
}
static byte[] getSignatureKey(String key, String dateStamp, String regionName, String serviceName) throws Exception {
byte[] kSecret = ("AWS4" + key).getBytes("UTF-8")
byte[] kDate = HmacSHA256(dateStamp, kSecret)
byte[] kRegion = HmacSHA256(regionName, kDate)
byte[] kService = HmacSHA256(serviceName, kRegion)
byte[] kSigning = HmacSHA256("aws4_request", kService)
return kSigning
}
public static String convertbyte(byte[] bytes) {
StringBuffer hexString = new StringBuffer();
for (int j = 0; j < bytes.length; j++) {
String hex = Integer.toHexString(0xff & bytes[j]);
if (hex.length() == 1) hexString.append('0');
hexString.append(hex);
}
return hexString.toString();
}
When I execute this def execute() is the first to execute, I have comprated the code with Postman only signature field is not accurate .Please help out as I am stuck in this for mostly two days

Connect to Azure Text Analytics from Console App without await

I am trying to call an Azure API (Text Analytics API) from a C# console application with a HttpRequest and I do not want to use any DLLs or await
but using the below snippet I am receiving "Bad Request". Can someone help me where it is going wrong.
public static void ProcessText()
{
string apiKey = "KEY FROM AZURE";
var client = new HttpClient();
var queryString = HttpUtility.ParseQueryString(string.Empty);
// Request headers
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", apiKey);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var requestUri = "https://eastus.api.cognitive.microsoft.com/text/analytics/v2.0/sentiment?" + queryString;
//HttpResponseMessage response;
// Request body
byte[] byteData = Encoding.UTF8.GetBytes("I really love Azure. It is the best cloud platform");
using (var content = new ByteArrayContent(byteData))
{
//content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var response = client.PostAsync(requestUri, content).Result;
Console.WriteLine(response);
Console.ReadLine();
}
}
string apiKey = "<<Key from Azure>>";
var client = new HttpClient();
var queryString = HttpUtility.ParseQueryString(string.Empty);
// Request headers
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", apiKey);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var requestUri = "https://**eastus**.api.cognitive.microsoft.com/text/analytics/v2.0/sentiment?" + queryString;
//HttpResponseMessage response;
var body = new
{
documents = new[]
{
new
{
ID="1", text="I really love Azure. It is the best cloud platform"
}
}
};
string json = JsonConvert.SerializeObject(body);
byte[] byteData = Encoding.UTF8.GetBytes(json);
dynamic item = null;
using (var con = new ByteArrayContent(byteData))
{
//content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var response = client.PostAsync(requestUri, con).Result;
if (response.StatusCode == HttpStatusCode.OK)
{
string res = string.Empty;
using (HttpContent content = response.Content)
{
Task<string> result = content.ReadAsStringAsync();
res = result.Result;
}
JavaScriptSerializer serializer = new JavaScriptSerializer();
item = serializer.Deserialize<object>(res);
}
}
Hi All, I could able to get the API output using the above approach

Move file after downloading from S3

Unable to Download a file from AWS S3 to the Downloads folder. However file is getting downloaded from AWS S3 server to the intermediate local server (E:\New**\E***\wwwroot\DownloadFiles). Now the issue is getting this file from (\DownloadFiles) this folder to the Downloads folder. Getting a error pop-up on attempting so.
return File(memory, tmpConType, Path.GetFileName(filePath));
Error Popup
Error-Popup-fromBrowser
Here is my full code for Download:
[HttpPost]
public async Task<ActionResult> DownloadFile(string fileName, string originalFilename, int clientId, int taskId)
{
using (LogContext.PushProperty("UserId", userId))
{
try
{
if (fileName != null && fileName != "")
{
var fName = fileName.Split("_")[0];
var s3Client = new AmazonS3Client(accesskey, secretkey, bucketRegion);
var s3companyFolder = "Company-" + companyId + "/" + "Client-" + clientId + "/" + "Job-" + taskId;
GetObjectRequest request = new GetObjectRequest
{
BucketName = bucketName + "/" + s3companyFolder,
Key = fName
};
using (GetObjectResponse response = await s3Client.GetObjectAsync(request))
{
using Stream responseStream = response.ResponseStream;
string tmpName = response.Metadata["x-amz-meta-filename"];
var tmpConType = response.Headers["Content-Type"];
string filePath = Path.Combine(hostingEnvironment.WebRootPath, "DownloadFiles");
filePath = Path.Combine(filePath, tmpName);
using FileStream outFile = System.IO.File.Create(filePath);
responseStream.CopyTo(outFile);
outFile.Dispose();
responseStream.Dispose();
var memory = new MemoryStream();
using (var stream = new FileStream(filePath, FileMode.Open))
{
await stream.CopyToAsync(memory);
}
if (System.IO.File.Exists(filePath))
System.IO.File.Delete(filePath);
memory.Position = 0;
return File(memory, tmpConType, Path.GetFileName(filePath));
}
}
return Json(new { success = true });
}
catch (Exception ex)
{
throw;
}
}
}
Thanks in Advance

PowerBi - how to authenticate to app.powerbi.com silently

I have tried the method outlined in the Microsoft docs
which involves creating an app in Active Directory and then having code something very similar to:
var authContextUrl = "https://login.windows.net/common/oauth2/authorize";
var authenticationContext = new AuthenticationContext(authContextUrl);
var redirectUri = "https://dev.powerbi.com/Apps/SignInRedirect";
var pp = new PlatformParameters(PromptBehavior.Auto);
var result = authenticationContext.AcquireTokenAsync(PowerBiApiResource, clientId, new Uri(redirectUri), pp).GetAwaiter().GetResult();
if (result == null)
{
throw new InvalidOperationException("Failed to obtain the PowerBI API token");
}
var token = result.AccessToken;
return token;
I got this code working but it always insisted on prompting for a username and password, which is a problem for a function app.
I have also tried the approach in the silent function specified here
https://community.powerbi.com/t5/Developer/Data-Refresh-by-using-API-Need-Steps/m-p/209371#M6614
static string getAccessTokenSilently()
{
HttpWebRequest request = System.Net.HttpWebRequest.CreateHttp("https://login.windows.net/common/oauth2/token");
//POST web request to create a datasource.
request.KeepAlive = true;
request.Method = "POST";
request.ContentLength = 0;
request.ContentType = "application/x-www-form-urlencoded";
//Add token to the request header
request.Headers.Add("Authorization", String.Format("Bearer {0}", token));
NameValueCollection parsedQueryString = HttpUtility.ParseQueryString(String.Empty);
parsedQueryString.Add("client_id", clientID);
parsedQueryString.Add("grant_type", "password");
parsedQueryString.Add("resource", resourceUri);
parsedQueryString.Add("username", username);
parsedQueryString.Add("password", password);
string postdata = parsedQueryString.ToString();
//POST web request
byte[] dataByteArray = System.Text.Encoding.ASCII.GetBytes(postdata); ;
request.ContentLength = dataByteArray.Length;
//Write JSON byte[] into a Stream
using (Stream writer = request.GetRequestStream())
{
writer.Write(dataByteArray, 0, dataByteArray.Length);
var response = (HttpWebResponse)request.GetResponse();
var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
dynamic responseJson = JsonConvert.DeserializeObject<dynamic>(responseString);
return responseJson["access_token"];
}
}
This code doesn't work.
Also this has issues, although I haven't tried it:
https://learn.microsoft.com/en-us/power-bi/developer/get-azuread-access-token
There doesn't appear to be anything up to date available that works that explains how to do this. Does anyone know how?
This is the best I've got so far. I have to create the application in AD using https://dev.powerbi.com/apps and then login using a powerbi pro userid and password, using the following code:
public static string GetPowerBiAccessToken(string tenantId, string clientId, string userId, string password)
{
var url = $"https://login.windows.net/{tenantId}/oauth2/token";
var request = (HttpWebRequest)WebRequest.Create(url);
request.KeepAlive = true;
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
var dataToPost = new Dictionary<string,string>
{
{"client_id", clientId},
{"grant_type", "password"},
{"resource", PowerBiApiResource},
{"username", userId},
{"password", password},
{"redirect_uri", "https://dev.powerbi.com/Apps/SignInRedirect" }
};
var postData = string.Empty;
foreach (var item in dataToPost)
{
if (!string.IsNullOrEmpty(postData))
postData += "&";
postData += $"{item.Key}={item.Value}";
}
var dataByteArray = System.Text.Encoding.ASCII.GetBytes(postData);
request.ContentLength = dataByteArray.Length;
using (var writer = request.GetRequestStream())
{
writer.Write(dataByteArray, 0, dataByteArray.Length);
}
var response = (HttpWebResponse)request.GetResponse();
var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
var responseJson = JsonConvert.DeserializeObject<dynamic>(responseString);
return responseJson["access_token"];
}
(P.S. I appreciate the request part of this code could be much better but having spent over 2 days trying to work this out, I'm just glad to have something that is working right now. Also the redirectUrl matches the one in my app, I'm not sure if its essential or not).
In the event of errors, I used Fiddler 4 to tell me exactly what the error was rather than just getting 400 or 401 in the app.

How can I simulate server for Unit test in Grails (Spock)?

I have written this simple service for doing subrequest via HTTPBuilder, to get instance of class representing obtained page for further use:
package cmspage
import groovyx.net.http.HTTPBuilder
import static groovyx.net.http.Method.GET
import static groovyx.net.http.ContentType.HTML
class CmsPageService {
static transactional = false
final String SUBREQUEST_HOST = "www.mydomainforsubrequest.com"
CmsPage getCmsPageInstance(Object request) {
String host = request.getServerName()
String url = request.getRequestURI()
HashMap queryMap = this.queryStringToMap(request.getQueryString())
return this.subRequest(host, url, queryMap)
}
CmsPage getCmsPageInstance(String host, String url, String queryString = null) {
HashMap queryMap = queryStringToMap(queryString)
return this.subRequest(host, url, queryMap)
}
private CmsPage subRequest(String host, String url, HashMap queryMap = null) {
CmsPage cmsPageInstance = new CmsPage()
HTTPBuilder http = new HTTPBuilder()
http.request("http://" + SUBREQUEST_HOST, GET, HTML) { req ->
uri.path = url
uri.query = queryMap
headers.'X-Original-Host' = 'www.mydomain.com'
response.success = { resp, html ->
cmsPageInstance.responseStatusCode = resp.status
if (resp.status < 400) {
cmsPageInstance.html = html
}
}
response.failure = { resp ->
cmsPageInstance.responseStatusCode = resp.status
return null
}
}
return cmsPageInstance
}
private HashMap queryStringToMap(String queryString) {
if (queryString) {
queryString = queryString.replace("?", "")
String[] splitToParameters = queryString.split("&")
HashMap queryMap = new HashMap()
splitToParameters.each {
String[] split = it.split("=")
for (int i = 0; i < split.length; i += 2) {
queryMap.put(split[i], split[i + 1])
}
}
return queryMap
} else return null
}
}
Now I need to write unit test for this service. I would like to use some simple html document to test it instead of testing some "live" site. But I do not know how?
Can anybody help me?
Jadler should suite you well. Check its documentation and this post on basic usage.