I have a app in which user can record video and an api to upload recorded video to azure. I am using below code
HttpClientHandler handler = new HttpClientHandler();
handler.MaxRequestContentBufferSize = int.MaxValue;
using (HttpClient httpClient = new HttpClient(handler)
{
MaxResponseContentBufferSize = int.MaxValue
})
{
MultipartFormDataContent content = new MultipartFormDataContent();
content.Add(new ByteArrayContent(chunks), "file", fileName);
HttpResponseMessage response = null;
response = await httpClient.PostAsync(new Uri(url), content);
return await response.Content.ReadAsStringAsync();
}
This is working only when either connection is wifi or on 3G video is less than of 10 sec. When I tried to upload video of size around 20-30 MB than it fails. In response I got status code 404 Not Found.
I also tried another way to upload but caught same error.
At last, I have changed my api code and send request with 1 mb chunks.
Related
I want to upload a static file to SharePoint using Graph API and HTTP Client.
We have a folder where the file is kept, now we have to read the file from the folder and upload it to SharePoint.
Stream stream = GetFile() //this will return file data as a Stream.
HttpClient httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization
= new AuthenticationHeaderValue("Bearer", token);
MultipartFormDataContent form = new MultipartFormDataContent();
var streamContent = new StreamContent(stream);
var imageContent = new ByteArrayContent(streamContent.ReadAsByteArrayAsync().Result);
imageContent.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/form-data");
form.Add(imageContent, "Test.pdf");
var response = httpClient.PostAsync(#"https://graph.microsoft.com/v1.0/sites/{siteId}/lists/{folderName}/drive/root:/childFolder/Test.pdf:/createUploadSession", form).Result;
We are getting BadRequest response for the above request.
According to the documentation no request body is required for createUploadSession endpoint but if you specify the body it must be json like this
Content-Type: application/json
{
"item": {
"#odata.type": "microsoft.graph.driveItemUploadableProperties",
"#microsoft.graph.conflictBehavior": "rename",
"name": "largefile.dat"
}
}
The response will contain uploadSession resource type.
To upload the file, or a portion of the file, you need to make a PUT request to the uploadUrl value received in the createUploadSession response. You can upload the entire file, or split the file into multiple byte ranges, as long as the maximum bytes in any given request is less than 60 MiB.
Resources:
driveItemUploadableProperties
uploadSession
Upload bytes to the upload session
I am calling to a rest api post method implement by me which has normal string parameters and one fileData byte array. I am just using application/json From Body technique to implement this service.
When i am calling to this api from C# code using HttpClient it is works fine for smaller files like 10-20 KBs. But when the file size is around 100-150 KBs PostAsync method is not getting anything untill the timeout happens. But when i call to same API from angular it is working fine for larger file sizes as well.
Below is my c# code block calling from client end. Please guide what is happening here.
Photo photo = new Photo
{
CustomerMobile = row["CustomerMobile"].ToString(),
PhotoCode = row["PhotoCode"].ToString(),
PhotoSize = row["PhotoSize"].ToString(),
TemplateId = int.Parse(row["TemplateId"].ToString()),
CreatedDate = DateTime.Parse(row["CreatedDate"].ToString()),
};
if (!string.IsNullOrEmpty(row["ExpiryDate"].ToString()))
photo.ExpiryDate = DateTime.Parse(row["ExpiryDate"].ToString());
var data = File.ReadAllBytes(row["PhotoUrl"].ToString());
photo.FileData = data;
photo.FileName = Path.GetFileName(row["PhotoUrl"].ToString());
using var client = new HttpClient();
HttpResponseMessage response = null;
client.BaseAddress = new Uri(Settings.Configurations.APIBaseServerURL);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add(Settings.Configurations.Application, Settings.Configurations.ApplicationId);
client.DefaultRequestHeaders.Add(Settings.Configurations.SessionID, sessionID);
response = client.PostAsync(url,
new StringContent(JsonConvert.SerializeObject(photo).ToString(),
Encoding.UTF8, "application/json")).Result;
I upload my files in azure data lake. I try to download that file through asp.net mvc application.I have adl path for that file. I can download below 150 MB files. But i can't download the more then 150 MB files. Time out error came.
My Code in the bellow...
public ActionResult Download(string adlpath)
{
String header = adlpath;
Console.WriteLine(header);
string[] splitedStr = header.Split('/');
var path = GenerateDownloadPaths(adlpath);
string filename = path["fileName"];
HttpResponseMessage val = DataDownloadFile(path["fileSrcPath"]);
byte[] filedata = val.Content.ReadAsByteArrayAsync().Result;
string contentType = MimeMapping.GetMimeMapping(filename);
var cd = new System.Net.Mime.ContentDisposition
{
FileName = filename,
Inline = true,
};
Response.AppendHeader("Content-Disposition", cd.ToString());
return File(filedata, contentType);
}
public HttpResponseMessage DataDownloadFile(string srcFilePath)
{
string DownloadUrl = "https://{0}.azuredatalakestore.net/webhdfs/v1/{1}?op=OPEN&read=true";
var fullurl = string.Format(DownloadUrl, _datalakeAccountName, srcFilePath);
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _accesstoken.access_token);
using (var formData = new MultipartFormDataContent())
{
resp = client.GetAsync(fullurl).Result;
}
}
return resp;
}
Image :
You should modify your code to use async and await. Your implementation blocks while retrieving the file and that is probably what times out:
public async Task<HttpResponseMessage> DataDownloadFile(string srcFilePath)
{
string DownloadUrl = "https://{0}.azuredatalakestore.net/webhdfs/v1/{1}?op=OPEN&read=true";
var fullurl = string.Format(DownloadUrl, _datalakeAccountName, srcFilePath);
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _accesstoken.access_token);
using (var formData = new MultipartFormDataContent())
{
resp = await client.GetAsync(fullurl);
}
}
return resp;
}
The return value of the method is changed to Task<HttpResponseMessage> and the async modifier is added.
Calling client.GetAsync is changed to use await instead of blocking by retrieving the Result property.
Your code may still timeout. I believe that there is a configurable limit on how long a request can take before it is aborted and if you still get a timeout you should investigate this.
Per my understanding, you could try to increase the HttpClient.Timeout (100 seconds by default) for your HttpClient instance.
HttpClient.Timeout
Gets or sets the timespan to wait before the request times out.
The default value is 100,000 milliseconds (100 seconds).
Moreover, if you host your application via Azure Web App, you may encounter an idle timeout setting of 4 minutes from Azure Load Balancer. You could change the idle timeout setting in Azure VM and Azure Cloud Service. Details you could follow here.
I have tried to create a simple console application.
We have a call system from 8x8 that provide a web streaming API but their documentation is very limited and nothing in C#.
The api service streams call statuses in near real time and I would like to get that 'stream' and be able to read and process it in realtime if possible. The response or Content Type is 'text/html'. But the actual body of the response can be declared as json - sample below:
{"Interaction":{"attachedData":{"attachedDatum":[{"attachedDataKey":"#pri","attachedDataValue":100},{"attachedDataKey":"callingName","attachedDataValue":999999999999},{"attachedDataKey":"cha","attachedDataValue":99999999999},{"attachedDataKey":"cnt","attachedDataValue":0},{"attachedDataKey":"con","attachedDataValue":0},{"attachedDataKey":"med","attachedDataValue":"T"},{"attachedDataKey":"pho","attachedDataValue":9999999999},{"attachedDataKey":"phoneNum","attachedDataValue":9999999999},{"attachedDataKey":"tok","attachedDataValue":999999999}]},"event":"InteractionCreated","inboundChannelid":9999999999,"interactionEventTS":9999999,"interactionGUID":"int-15b875d0da2-DJOJkDhDsrh3AIaFP8VkICv9t-phone-01-testist","resourceType":0}}
I have seen several posts concerning httpClient and the GetAsync methods but none of these appear to work as they appear to be for calls when a response is made, not something that constantly has a response.
Using fiddler for the call it does not appear to close so the stream is constantly running, so fiddler does not display any data until a separate user or instance connects.
When I use a browser the content is 'streamed' to the page and updates automatically and shows all the content (as above).
The api contains authentication so when another client connects and retrieves data the connected client closes and finally I am able to see the data that was gathering.
This is the code so and does return the big stream when another client connects but ideally I want a real time response and appears to just get stuck in the GETASYNC method:
var response = await client.GetAsync(address, HttpCompletionOption.ResponseHeadersRead);
if (response.IsSuccessStatusCode)
{
var responseContent = response.Content;
string responseString = await responseContent.ReadAsStringAsync();
Console.WriteLine(responseString);
}
Hopefully that's enough information for one of you clever people to help me in my predicament.
I was also having an issue consuming their streaming API and the examples I found that worked with the Twitter and CouchBase streaming API's did not work with 8x8. Both Twitter and CouchBase send line terminators in their pushes so the solution relied on ReadLine to pull in the feed. Since 8x8 does not send terminators you'll need to use ReadBlock or better ReadBlockAsync.
The following code shows how to connect using credentials and consume their feed:
private static async Task StreamAsync(string url, string username, string password)
{
var handler = new HttpClientHandler()
{
Credentials = new NetworkCredential {UserName = username, Password = password},
PreAuthenticate = true
};
// Client can also be singleton
using (var client = new HttpClient(handler))
{
client.Timeout = TimeSpan.FromMilliseconds(Timeout.Infinite);
var request = new HttpRequestMessage(HttpMethod.Get, url);
request.Headers.Connection.Add("keep-alive");
using (var response = await client.SendAsync(
request,
HttpCompletionOption.ResponseHeadersRead))
{
using (var body = await response.Content.ReadAsStreamAsync())
{
using (var reader = new StreamReader(body))
{
while (!reader.EndOfStream)
{
var buffer = new char[1024];
await reader.ReadBlockAsync(buffer, 0, buffer.Length);
Console.WriteLine(new string(buffer));
}
}
}
}
}
}
I'm working on a Windows 10 project, one of my tasks is to send files to server in multipart request, so I achieve that by the following code, it is working well and files received from server and task completed.
Code:
System.Net.Http.HttpContent stringContent = new System.Net.Http.StringContent(imageFileName);
System.Net.Http.HttpContent bytesContent;
var client = new System.Net.Http.HttpClient();
var formData = new System.Net.Http.MultipartFormDataContent();
formData.Add(stringContent, "type");
foreach (byte[] image in imageFileName.GetImagesList())
{
bytesContent = new System.Net.Http.ByteArrayContent(image);
bytesContent.Headers.ContentType = MediaTypeHeaderValue.Parse("image/jpeg");
formData.Add(bytesContent, "images", "file_" + imageFileName.GetImagesList().IndexOf(image) + ".jpg");
}
var response = client.PostAsync(resourceAddress, formData).Result;
Then when we've moved to production environment, the firewall rejected this request and caught multiple hack attempts such as:
Http Headers Injection
SQL Injection by '#'
rm execution attempt
Backtick command execution attempts
vi execution attempts ...... and many more ....
And all this attempts, are caught for the contents of the JPEG file!
So I though that I should use HttpStreamContent instead, and tried the following code:
HttpMultipartFormDataContent multipartContent = new HttpMultipartFormDataContent();
HttpStreamContent streamContent;
Stream stream;
foreach (byte[] image in imageFileName.GetImagesList())
{
stream = new MemoryStream(image);
streamContent = new HttpStreamContent(stream.AsInputStream());
streamContent.Headers.ContentType = new HttpMediaTypeHeaderValue("image/jpeg");
multipartContent.Add(streamContent, "images", "file_" + imageFileName.GetImagesList().IndexOf(image) + ".jpg");
}
multipartContent.Add(new HttpStringContent(imageFileName), "type");
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, resourceAddress);
request.Content = multipartContent;
HttpResponseMessage response = await httpClient.SendRequestAsync(request).AsTask(cts.Token);
But Unfortunately I've got same result.
And the most important point is that the same web service (which I'm trying to call) is required to be implemented on Android & IOS with same functionality (multipart request) so the request from Android & IOS will be passed through the same Firewall, and it is working well from Android & IOS even on production!!!!