Post audio through URL Request for transcription - c#

I am trying to send an audio for processing to an API. I have the audio in the filePath variable. The code is working fine, the request is successfull because the audio sent though the URL is null. I tried to log the jsonresult to view its content, and it's showing that the audio-duration is null, which is not the case in the audio saved in my local computer.
Here is the method:
private void Transcribe()
{
if (isRecording)
{
Microphone.End("");
isRecording = false;
}
if (clip == null)
{
Debug.LogError("No audio clip found. Please record audio first.");
return;
}
SavWav.Save("recording", clip);
byte[] audioData = null;
string filePath = Application.persistentDataPath + "/recording.wav";
if(File.Exists(filePath)){
audioData = File.ReadAllBytes(filePath);
}
else{
Debug.LogError("File not found at " + filePath);
return;
}
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("https://api.assemblyai.com/v2/");
client.DefaultRequestHeaders.Add("authorization", API_Key);
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "upload");
request.Headers.Add("Transfer-Encoding", "chunked");
ByteArrayContent content = new ByteArrayContent(audioData);
content.Headers.ContentType = new MediaTypeHeaderValue("audio/wav");
request.Content = content;
HttpResponseMessage response = client.SendAsync(request).Result;
// Check if the response is successful
if (response.IsSuccessStatusCode)
{
// Read the response content as a string
string jsonResult = response.Content.ReadAsStringAsync().Result;
// Parse the JSON response to get the upload URL
var json = JSON.Parse(jsonResult);
string uploadUrl = json["upload_url"].Value;
// Send a POST request to the transcript endpoint
StringContent payload = new StringContent("{\"audio_url\": \"" + uploadUrl + "\"}",
Encoding.UTF8, "application/json");
HttpResponseMessage transcriptResponse = client.PostAsync("transcript", payload).Result;
// Check if the transcript response is successful
if (transcriptResponse.IsSuccessStatusCode)
{
// Read the transcript response content as a string
string transcriptJson = transcriptResponse.Content.ReadAsStringAsync().Result;
// Parse the JSON response to get the transcript text
var transcript = JSON.Parse(transcriptJson);
string transcriptText = transcript["text"].Value;
Debug.Log(transcriptJson);
// Update the UI or show the transcription result
transcribedTextLabel.text = transcriptText;
}
else
{
Debug.LogError("Failed to transcribe audio: " + transcriptResponse.ReasonPhrase);
}
}
else
{
Debug.LogError("Failed to upload audio: " + response.ReasonPhrase);
}
}
private class UploadItem
{
public string upload_url { get; set; }
}

Related

.net core bad request for http GET and sending body

Im trying to send http GET request butIm getting 400 BadRequest.
I need just someone to confirm that I packed request properly.
I assume that my content is not good?
var um = "123456";
var request = new HttpRequestMessage
{
Method = HttpMethod.Get,
RequestUri = new Uri($"{_iOptions.Server}{_iOptions.Method.GetData}")
};
request.Content = new ByteArrayContent(Encoding.UTF8.GetBytes("{ \"um\": " + um + " }"));
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var responseMessage = await _httpClient.SendAsync(request).ConfigureAwait(false);
responseMessage.EnsureSuccessStatusCode();
GetResponse response = await responseMessage.Content.ReadAsAsync<GetResponse>();
if (response.Code == (int)System.Net.HttpStatusCode.OK)
{
response.Success = true;
return response;
}
else
{
response.Success = false;
return response;
};
Because the data format is application/json, you have to use HttpMethod.Post. And the value should add double quotes in (Encoding.UTF8.GetBytes("{ \"um\": \"" + um + "\" }").
var client = new HttpClient();
var um = "123456";
var request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri("https://localhost:...")
};
request.Content = new ByteArrayContent(Encoding.UTF8.GetBytes("{ \"um\": \"" + um + "\" }"));
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var responseMessage = await client.SendAsync(request).ConfigureAwait(false);
responseMessage.EnsureSuccessStatusCode();
//...
In addition, ensure that the backend is received by object.
[HttpPost]
public IActionResult get([FromBody]MyModel myModel)
{
return Ok(myModel.um);
}
And the model
public class MyModel
{
public string um { get; set; }
}

Python code to c# .net for HTTP Post to API

I need help converting the follow Python code to c# .net. This code is posting/uploading a text file to a webserver. The Python script has been tested and works. I have tried a few solutions with HTTPClient and WebRequest with no luck. Any guidance will be greatly appreciated.
# request a session
client = requests.session()
# Establish the URL
newurl = 'https://localhost/filedist/upload/'
source_file = 'data/test.txt'
headers = {'Authorization': 'Token MYTOKEN'}
# Populate the values with our environment and target path
values = dict(environment='dev', path='Business/Tools')
files = dict(file=open(source_file, 'rb'))
r = client.post(newurl, files=files, data=values, headers=headers)
Here is my latest attempt, which currently is getting a 'Forbidden' error.
public static async Task<string> UploadFile(string path, string fileName)
{
var client = new HttpClient();
string NewURL = "https://localhost/filedist/upload/";
string SourceFile = path;
var content = new MultipartFormDataContent();
client.DefaultRequestHeaders.Add("Authorization", "Token MYTOKEN");
Stream fs = System.IO.File.Open(path, FileMode.Open, FileAccess.Read, FileShare.None);
content.Add(CreateFileContent(fs, fileName, "text/plain"));
var parameters = new Dictionary<string, string> { { "environment", "dev" }, { "path", "Business/Tools" } };
content.Add(new FormUrlEncodedContent(parameters));
var response = await client.PostAsync(NewURL, content);
response.EnsureSuccessStatusCode();
if (response.IsSuccessStatusCode)
{
string responseString = response.Content.ReadAsStringAsync().Result;
return "true";
}
else
{
return "false";
}
}
private static StreamContent CreateFileContent(Stream stream, string fileName, string contentType)
{
try
{
var fileContent = new StreamContent(stream);
fileContent.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("form-data")
{
Name = "UploadedFile",
FileName = "\"" + fileName + "\""
};
fileContent.Headers.ContentType = new MediaTypeHeaderValue(contentType);
return fileContent;
}
catch (Exception ex)
{
return null;
}
}
Thanks
I am not 100% on this, but I don't think you can set the authorization header that way. Try using the client authorization header type.
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Token", "MYTOKEN");

Send Json as body and file webrequest

How to send both body and also a file?
From the API Guide: "Upload Requests are submitted with multiple parts: body (request) and file buffer (file)."
I know how to send only a Json as body, but I need now to seng Json as body and also a file.
My code looks something like:
const string WEBSERVICE_URL = "https://myurl.com";
var webRequest = System.Net.WebRequest.Create(WEBSERVICE_URL);
webRequest.Method = "POST";
webRequest.ContentType = "multipart/form-data;boundary=12345678912345678912345678";
webRequest.Headers.Add("Authorization:7786FFFGFDDDP");
And:
string json="{"\some json"\ :\"here\" }"
using (var streamWriter = new StreamWriter(webRequest.GetRequestStream()))
{
streamWriter.Write(json);
}
var httpResponse = (HttpWebResponse)webRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
Console.WriteLine(result.ToString());
}
But how to send both file and body together? I mean I want also to upload some file wih path #c:\\myFile.txt
I need to do this in a Xamarin application. Post an image to a web api with token based authentication. I made some changes in code to be posible use in a web application.
public async void SendFile()
{
using (System.IO.FileStream stream = System.IO.File.Open(#"c:\file.txt", System.IO.FileMode.Open))
{
var content = new System.Net.Http.MultipartFormDataContent();
content.Add(new System.Net.Http.StreamContent(stream),
"\"file\"",
"Path to your file (ex: c:\temp\file.txt");
await PostItemAsyncWithToken("url to post", content, "accessToken");
}
}
public async System.Threading.Tasks.Task<bool> PostItemAsyncWithToken(string url, System.Net.Http.HttpContent content, string accessToken)
{
try
{
using (var httpClient = new System.Net.Http.HttpClient())
{
httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", accessToken);
System.Net.Http.HttpResponseMessage response = await httpClient.PostAsync(url, content).ConfigureAwait(false);
if (response.IsSuccessStatusCode)
{
return true;
}
else
{
return false;
}
}
}
catch (System.Exception ex)
{
throw new System.Exception("Error message", ex);
}
}

Send image to WebApi service

I'm making a project on Windows Phone where user can take a photo, save it on phone and next upload on my server. So there are two projects, WP8.1 and ASP.NET WEB API.
Currently I don't know how to upload photo to my server(from phone), I even don't know how to catch it in API. What's the best way to make it?
Here is my method to show on the screen(phone), picture which was taken by user.
private async void LoadCapturedphoto(string filename)
{
//load saved image
StorageFolder pictureLibrary = KnownFolders.SavedPictures;
StorageFile savedPicture = await pictureLibrary.GetFileAsync(filename);
ImageProperties imgProp = await savedPicture.Properties.GetImagePropertiesAsync();
var savedPictureStream = await savedPicture.OpenAsync(FileAccessMode.Read);
//set image properties and show the taken photo
bitmap = new WriteableBitmap((int)imgProp.Width, (int)imgProp.Height);
await bitmap.SetSourceAsync(savedPictureStream);
takenImage.Source = bitmap;
takenImage.Visibility = Visibility.Visible;
}
I think that I should convert WriteableBitmap to Byte[], send these Byte[] by API to server and on server convert Byte[] to JPG/PNG/etc.
private byte[] ConvertBitmapToByteArray(WriteableBitmap bitmap)
{
WriteableBitmap bmp = bitmap;
using (Stream stream = bmp.PixelBuffer.AsStream())
{
MemoryStream memoryStream = new MemoryStream();
stream.CopyTo(memoryStream);
return memoryStream.ToArray();
}
}
Any ideas? Do you think it's good idea to make it like that? WriteableBitmap -> Byte[] and next on server Byte[] -> JPG/PNG etc. Is it even possible?
If it can be done much more easier please write some samples.
it's my method for calling api methods
public string apiCommand(string api, string json)
{
using (var httpClient = new HttpClient())
{
HttpContent content = new StringContent(json, Encoding.UTF8);
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
HttpResponseMessage response = httpClient.PostAsync(Variables.apiURL + api, content).Result;
response.EnsureSuccessStatusCode();
Task<string> responseBody = response.Content.ReadAsStringAsync();
//var msg = new MessageDialog(responseBody.Result.ToString());
if (response.StatusCode.ToString() != "OK")
{
return "ERROR: " + response.StatusCode.ToString();
}
else
{
return "SUCCES: " + responseBody.Result.ToString();
}
}
}
You need to use multipart/form-data request to the server. You can send the json to the web api using payload field (another alternative is send every field separately, but you need reflection to do that.)
This maybe can help you:
public string UploadUserPictureApiCommand(string api, string json, byte[] picture)
{
using (var httpClient = new HttpClient())
{
MultipartFormDataContent form = new MultipartFormDataContent();
form.Add(new StringContent(json), "payload");
form.Add(new ByteArrayContent(picture, 0, picture.Count()), "user_picture", "user_picture.jpg");
HttpResponseMessage response = await httpClient.PostAsync(api, form);
response.EnsureSuccessStatusCode();
Task<string> responseBody = response.Content.ReadAsStringAsync();
if (response.StatusCode.ToString() != "OK")
{
return "ERROR: " + response.StatusCode.ToString();
}
else
{
return "SUCCES: " + responseBody.Result.ToString();
}
}
}
I handle image and word files in my project by this way, hope it helps.
1) Server side, I have a generic api method to process Json requests.
[HttpPost]
public HttpResponseMessage ProcessRequest([FromBody] string sJsonRequest)
{
ResponseMsg rspMsg = null;
RequestMsg oRequestMsg = null;
string sDeteializeMsg = "";
try
{
string sUnescapeJsonData = System.Uri.UnescapeDataString(sJsonRequest);
sJsonRequest = sUnescapeJsonData;
oRequestMsg = (RequestMsg)JsonHelper.Deserialize(typeof(RequestMsg), sJsonRequest);
}
catch (Exception ex)
{
...
}
if (oRequestMsg == null)
{
return AppHelper.GetUTF8PlainTextHttpResponse(#"Invalid request message.");
}
rspMsg = new ResponseMsg(oRequestMsg);
string sJsonRet = "";
try
{
if(oRequestMsg.RequestType==SavingFile)
{
byte[] bytes = System.Convert.FromBase64String(oRequestMsg.Base64Data);
System.IO.File.WriteAllBytes(sFileName, bytes);
....
}
//update rspMsg ....
}
catch (Exception ex)
{
...
}
finally
{
sJsonRet = JsonHelper.Serialize(rspMsg);
}
return AppHelper.GetUTF8PlainTextHttpResponse(sJsonRet);
}
Client side,
1) call through .net code, I use system.Net.webclient,
system.Net.webclient cli=new system.Net.webclient();
cli.Credentials = Credentials;
cli.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
//http://blogs.msdn.com/b/jmstall/archive/2012/04/16/how-webapi-does-parameter-binding.aspx
sJsonRequest = "=" + EscapeDataStringBig(sJsonRequest);
response = cli.UploadString(sRemoteUrl, "POST", sJsonRequest);
ResponseMsg rsp = (ResponseMsg)JsonHelper.Deserialize(typeof(ResponseMsg), response);
return rsp;
2) call it through JavaScript, usually I will create a method in website controller and forward the json request to the method defined as above. if your javascript code and api code share same json objects, it is quite easy.
2.1) web site controller code,
[HttpPost]
public ActionResult AjaxRequest(int nPostType = -1, string sJsonObject = "")
{
try
{
WebModelAjaxRequestTypes nReqType = (WebModelAjaxRequestTypes)nPostType;
bool bIsBase64Data = IsBase64Request(nReqType);
string sJsonRet = "";
if (!bIsBase64Data)
{
....
}
else
{
//base64 content requests
string sBase64Data = sJsonObject;
//put the string into a json request and send it to api call. and get the return => sJsonRet
}
return Content(sJsonRet); }
catch (Exception ex)
{
....
}
}
2.2) JavaScript ajax call sample code:
var type = "POST";
var sContentType = "";
var sData = ""
if (bIsBase64) {
//sJsonParas is base64 string. don't use encodeURI to encode it.!!!
sContentType = 'application/json; charset=utf-8';
sData = '{ "nPostType" :' + nPostType.toString() + ',"sJsonObject" : "' + sJsonParas + '" }';
}
else {
sContentType = "application/x-www-form-urlencoded; charset=UTF-8";
sData = "nPostType=" + nPostType.toString() + "&sJsonObject=" + encodeURIComponent(sJsonParas);
}
jQuery.ajax({
url: sUrl,
type: type,
data: sData,
contentType: sContentType,
success: function (result) {
....
},
error: function (jqXHR, textStatus, errorThrown) {
....
},
complete: function (jqXHR, textStatus) {
....
} //end complete
});

Post string and bytearray to server

I have done POSTING and GETing from server using string post data, but now i have the next WebService:
submitFeedback(String token, String subject, String body, byte[] photo, byte[] video);
private void PostFeedbackData()
{
if (GS.online != true)
{
MessageBox.Show(GS.translations["ErrorMsg0"]);
}
else
{
HttpWebRequest request = HttpWebRequest.CreateHttp("https://****/feedback");
request.Method = "POST";
request.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), request);
}
}
void GetRequestStreamCallback(IAsyncResult callbackResult)
{
HttpWebRequest myRequest = (HttpWebRequest)callbackResult.AsyncState;
// End the stream request operation
Stream postStream = myRequest.EndGetRequestStream(callbackResult);
// Create the post data
string postData = "";
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
postData = "{\"jsonrpc\": \"2.0\", \"method\": \"getUserSchedule\", \"params\":[" + "\"" + (App.Current as App).UserToken + "\",\"" + FeedbackTitle.Text + "\",\"" + FeedbackContent.Text + "\",\"" + imageBytes + "\"], \"id\": 1}";
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
// Add the post data to the web request
postStream.Write(byteArray, 0, byteArray.Length);
postStream.Close();
// Start the web request
myRequest.BeginGetResponse(new AsyncCallback(GetResponsetStreamCallback), myRequest);
});
}
Look at post data - it is a string, i can't place there imageBytes array. How to do it?
Is there any reason for using HttpWebRequest ?
I am asking that because i think that the correct way of sending files to a service is by multipartform data. With HttpWebRequest you have to manually implement that.
Here is an example that is using Microsoft's HttpClient that might work for you:
public async Task<string> submitFeedback(String token, String subject, String body, byte[] photo, byte[] video) {
var client = new HttpClient();
var content = new MultipartFormDataContent();
// Some APIs do not support quotes in boundary field
foreach (var param in content.Headers.ContentType.Parameters.Where(param => param.Name.Equals("boundary")))
param.Value = param.Value.Replace("\"", String.Empty);
var tok = new StringContent(token);
content.Add(tok, "\"token\"");
var sub = new StringContent(subject);
content.Add(tok, "\"subject\"");
// Add the Photo
var photoContent = new StreamContent(new MemoryStream(photo));
photoContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "\"photo\"",
FileName = "\"photoname.jpg\""
};
photoContent.Headers.ContentType = MediaTypeHeaderValue.Parse("image/jpeg");
content.Add(photoContent);
// Add the video
var videoContent = new StreamContent(new MemoryStream(video));
videoContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "\"video\"",
FileName = "\"videoname.jpg\""
};
videoContent.Headers.ContentType = MediaTypeHeaderValue.Parse("video/mp4");
content.Add(videoContent);
HttpResponseMessage resp;
try {
resp = await client.PostAsync("SERVER_URL_GOES_HERE", content);
}
catch (Exception e)
{
return "EXCEPTION ERROR";
}
if (resp.StatusCode != HttpStatusCode.OK)
{
return resp.StatusCode.ToString();
}
var reponse = await resp.Content.ReadAsStringAsync();
return reponse;
}
Change accordingly.
Note: HttpClient is also using HttpWebRequest under the hood.
Also I don't think its a good idea to have the UI thread making the request. That makes no sense since you are blocking the interface and making the async theory useless.

Categories

Resources