I want to download file from URL (like video). I know how to do it using WebClient, but now I want to start download from some point of this file (for example from half) as far as I know it is impossible to do it using WebClient. So how can I do it?
This should work if server supports byte range
using (var httpClient = new HttpClient())
{
var bytesToSkip = 100_000;
var httpRequestMessage = new HttpRequestMessage
{
RequestUri = new Uri("file to download"),
Method = HttpMethod.Get,
Headers = { Range = new RangeHeaderValue(bytesToSkip, null)}
};
var response = await httpClient.SendAsync(httpRequestMessage);
var content = await response.Content.ReadAsByteArrayAsync();
}
Related
I'm fairly new to use HTTPClient and sending REST requests to APIs, I'm currently practicing multipart upload using this Google Drive API endpoint:
POST https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart
There's an instruction that states there to split the request body into two parts, I tried to recreate this but was unable to do so.
https://developers.google.com/drive/api/guides/manage-uploads#multipart
Here's my current code:
async void UploadFile(StorageFile fileName)
{
using (HttpClient client = new HttpClient())
{
// Opens files and convert it to stream
var resultStream = await fileName.OpenReadAsync();
var fileStreamContent = new StreamContent(resultStream.AsStream());
// Create file MetaData
var fileMetaData = JsonConvert.SerializeObject(
new { name = fileName.Name, mimetype = fileName.ContentType });
// Create POST request
var requestMessage = new HttpRequestMessage(HttpMethod.Post, uploadFileEndpoint);
requestMessage.Headers.Authorization = new AuthenticationHeaderValue(tokenType, accessToken);
// Add request body
requestMessage.Content = new StringContent(fileMetaData, Encoding.UTF8, "application/json");
requestMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("multipart/related");
var response = await client.SendAsync(requestMessage);
string responseString = await response.Content.ReadAsStringAsync();
output(responseString);
}
}
Any help would be greatly appreciated, thank you!
According to the documentation on Perform a multipart upload (HTTP tab), you need the MultipartFormDataContent as suggested by #Jeremy.
There are a few things needed to perform/migrate:
Add AuthenticationHeaderValue into client.DefaultRequestHeaders.Authorization.
Create a StreamContent instance, fileStreamContent (which you have done) and specify its Headers.ContentType.
Create a StringContent instance, stringContent (which you have done).
Append both StreamContent and StringContent into the MultipartFormDataContent instance, formData.
Specify the formData's Headers.ContentType as requested in API docs.
Post the formData with await client.PostAsync(/* API Url */, formData);
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(tokenType, accessToken);
// Opens files and convert it to stream
var resultStream = await fileName.OpenReadAsync();
var fileStreamContent = new StreamContent(resultStream.AsStream());
fileStreamContent.Headers.ContentType = new MediaTypeHeaderValue(fileName.ContentType);
// Create file MetaData
var fileMetaData = JsonConvert.SerializeObject(new { name = fileName.Name, mimetype = fileName.ContentType });
var stringContent = new StringContent(fileMetaData, Encoding.UTF8, "application/json");
// Create POST request
MultipartFormDataContent formData = new MultipartFormDataContent();
formData.Add(stringContent, "metadata");
formData.Add(fileStreamContent, "media");
formData.Headers.ContentType = new MediaTypeHeaderValue("multipart/related");
var response = await client.PostAsync(uploadFileEndpoint, formData);
string responseString = await response.Content.ReadAsStringAsync();
}
I am in the process of creating a proxy server that makes a request to a PDF Blob link then takes the request to setup its HttpResponse Header which we sent to the client. This diagram should explain
As of now, I am successful at making the request to get the pdf content however I am not sure how to send that back to the user. I have followed other Stackoverflow post such as this one : https://stackoverflow.com/a/43232581/10541061
I turn the response message in step 3 of the diagram to a stream and sent it back in the new HttpResponseMessage content.But instead of PDF content , I get a json file
What I want to return to the client
What I am actually returning to the client
Here is the code I am using to create this proxy endpoint
[AllowAnonymous]
[HttpGet("openPDF")]
public async Task<HttpResponseMessage> OpenPDF([FromQuery] string url)
{
var _httpClient = _httpClientFactory.CreateClient();
var response = await _httpClient.GetAsync(url);
var stream = await response.Content.ReadAsStreamAsync();
HttpResponseMessage message = new HttpResponseMessage(HttpStatusCode.OK);
message.Content = new StreamContent(stream);
message.Content.Headers.ContentLength = stream.Length;
message.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
return message;
}
EDIT
Ok so this actually sends back the PDF when I write the proxy like this
[AllowAnonymous]
[HttpGet("openPDF")]
public async Task<FileStreamResult> OpenPDF([FromQuery] string url)
{
var fileStream = new MemoryStream();
var _httpClient = _httpClientFactory.CreateClient();
var file = await _httpClient.GetStreamAsync(url).ConfigureAwait(false);
await file.CopyToAsync(fileStream);
fileStream.Position = 0;
return File(fileStream, "application/pdf", "filename.pdf");
}
The problem is I want to update the content-disposition to inline so I can force this to open in the browser instead of downloading.So I decided to take the filestream and injecting that in the httpResponseMessage.content instead but that still didn't work. It would continue to send me a json file
[AllowAnonymous]
[HttpGet("openPDF")]
public async Task<HttpResponseMessage> OpenPDF([FromQuery] string url)
{
var fileStream = new MemoryStream();
var _httpClient = _httpClientFactory.CreateClient();
var file = await _httpClient.GetStreamAsync(url).ConfigureAwait(false);
await file.CopyToAsync(fileStream);
fileStream.Position = 0;
HttpResponseMessage message = new HttpResponseMessage(HttpStatusCode.OK);
message.Content = new StreamContent(fileStream);
message.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
return message;
}
To be honest, I thought defining the content-type should suffice but guess not
This is pretty straight forward for .NET 6... suspect it should be roughly the same for .NET 4x... This uses the NuGet package Azure.Storage.Blobs
https://github.com/Azure/azure-sdk-for-net/blob/Azure.Storage.Blobs_12.13.1/sdk/storage/Azure.Storage.Blobs/README.md
[HttpGet("stream")]
public async Task GetBlobAsync()
{
var url = new Uri("https://path.to.blob.content/xxx");
var blobClient = new BlobClient(url);
Response.Headers.Add("Content-Type", "application/pdf");
Response.Headers.Add("Content-Disposition", #"attachment;filename=""intended file name.pdf""");
await blobClient.DownloadToAsync(Response.Body);
}
for .NET 4x.
try to add:
result.Content.Headers.ContentDisposition =
new ContentDispositionHeaderValue("inline")
{
FileName = "filename.pdf"
};
Let me preface by stating that I' somewhat new to dealing with zipping/unzipping/reading/reading files. That being said, I'm doing a PoC that will retrieve data via api and write the responses to a database. The response is a zip file and inside this zip is the json data I will be reading and writing to the database.
I'm having some trouble unzipping and reading the information. Please find the code below:
HttpClient client = new HttpClient();
HttpRequestMessage request = new HttpRequestMessage
{
Method = HttpMethod.Get,
RequestUri = new Uri(baseUrl),
Headers =
{
{ "X-API-TOKEN", apiKey },
},
};
using (var response = await client.SendAsync(request))
{
response.EnsureSuccessStatusCode();
var body = await response.Content.ReadAsStringAsync();
// here is where I am stuck - not sure how I would unzip and read the contents
}
Thanks
Assuming you actually have a .zip file, you don't need a MemoryStream, you just need to pass the existing stream to ZipArchive
static HttpClient client = new HttpClient(); // always keep static client
async Task GetZip()
{
using var request = new HttpRequestMessage(HttpMethod.Get, new Uri(baseUrl))
{
Headers = {
{ "X-API-TOKEN", apiKey },
},
};
using var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
response.EnsureSuccessStatusCode();
using var stream = await response.Content.ReadAsStreamAsync();
await ProcessZip(stream);
}
async Task ProcessZip(Stream zipStream)
{
using var zip = new ZipArchive(zipStream, ZipArchiveMode.Read);
foreach (var file in zip.Entries)
{
using var entryStream = file.Open();
await ....; // do stuff here
}
}
You can convert body to a byte array and then unzip it using MemoryStream.
byte[] bytes = Encoding.ASCII.GetBytes(body);
using (var mso = new MemoryStream(bytes)) {
using (var gs = new GZipStream(msi, CompressionMode.Decompress)) {
CopyTo(gs, mso);
}
return Encoding.UTF8.GetString(mso.ToArray());
}
We have a requirement of sending the jpeg files of a given directory to a Xamarin App.
Following is the code in the Web API.
public HttpResponseMessage DownloadMutipleFiles()
{
name = "DirectoryName";
var content = new MultipartContent();
var ids = new List<int> { 1,2};
var objectContent = new ObjectContent<List<int>>(ids, new System.Net.Http.Formatting.JsonMediaTypeFormatter());
content.Add(objectContent);
var file1Content = new StreamContent(new FileStream(#"D:\Photos\" + name+"\\"+ "BL1408037_20191031124058_0.jpg", FileMode.Open));
file1Content.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("image/jpeg");
content.Add(file1Content);
var file2Content = new StreamContent(new FileStream(#"D:\Photos\" + name + "\\" + "BL1408037_20191031124058_1.jpg", FileMode.Open));
file2Content.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("image/jpeg");
content.Add(file2Content);
var response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = content;
return response;
}
Can some one help out with how to read from Xamarin app? Thanks in advance
This is the function I was able to use to send an image as a multi part data file! I just took the byte array given to me by the Xamarin Essentials image picker and passed it into this function:
public async Task SubmitImage(byte[] image, string imageName)
{
using (var client = new HttpClient())
{
string url = $"..."; // URL goes here
var token = Preferences.Get("AccessToken", "");
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
var stream = new MemoryStream(image);
var content = new StreamContent(stream);
//Without a name we can't actually put the file in IFormFile. We need the equivalent
//"name" value to be "file" (used if you upload via an <input> tag). We could call it
//anything but file is simple
content.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
FileName = imageName,
Name = "file"
};
content.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
var multipartContent = new MultipartFormDataContent();
multipartContent.Add(content);
var result = await client.PostAsync(url, multipartContent);
}
}
You can test this using a console application as well and just send over a picture from your computer, instead of doing this through the app
I have a bot running on http://localhost:3978/api/messages.
Instead of debugging it using an emulator, can I go about using a http post request to the messaging endpoint of the bot?
If so, how do I go about doing it?
I am using c# microsoft bot framework, and I am new to this application.
I do not want to use any channels or DirectLine api, just using Httpclient.
You can do this with C# using code similar to below. Note that you would have to construct an Activity to send by setting the appropriate properties for your needs, which is not included in this code.
//make a call to get an auth token
string token;
using (var client = new WebClient())
{
var values = new NameValueCollection();
values["grant_type"] = "client_credentials";
values["client_id"] = "YOUR APP ID";
values["client_secret"] = "NcOXRwb51joibEfzUuNE04u";
values["scope"] = "YOUR APP ID/.default";
var response =
client.UploadValues("https://login.microsoftonline.com/botframework.com/oauth2/v2.0/token", values);
var responseString = Encoding.Default.GetString(response);
var result = JsonConvert.DeserializeObject<ResponseObject>(responseString);
token = result.access_token;
}
//you will need to adjust this value for your project.
//this example for a proxy project so the service url here is
//just an arbitrary endpoint I was using to send activities to
activity.ServiceUrl = "http://localhost:4643/api/return";
var jsonActivityAltered = JsonConvert.SerializeObject(activity);
using (var client = new WebClient())
{
client.Headers.Add("Content-Type", "application/json");
client.Headers.Add("Authorization", $"Bearer {token}");
try
{
var btmResponse = client.UploadString("http://localhost:3971/api/messages", jsonActivityAltered);
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
Have you tried using something like postman? (it's free and easy to use)
https://www.getpostman.com/
You can also write scripts in postman
otherwise you can just go to the endpoint of your API in the browser
http://localhost:3978/api/
I see you mentioned you wanted to make a console application.
You could do that. I'd suggest using postman though.
Here is an example of sending a file as well as some querystring data and Authentication using a Bearer token.
Sorry it may not be exact. Had to do a bit of copy pasting/deleting from some code examples if have
using (HttpClient client = new HttpClient())
{
JObject jsonModel = new JObject();
client.BaseAddress = new Uri("http://localhost:3978/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", AuthToken);
using (var multipartFormDataContent = new MultipartFormDataContent())
{
var values = new[]
{
new KeyValuePair<string, string>("firstname", lastname),
new KeyValuePair<string, string>("lastname", lastname),
new KeyValuePair<string, string>("payloadFile", FileName)
};
foreach (var keyValuePair in values)
{
multipartFormDataContent.Add(new StringContent(keyValuePair.Value),
String.Format("\"{0}\"", keyValuePair.Key));
}
ByteArrayContent fileContent = new ByteArrayContent(File.ReadAllBytes(HttpContext.Current.Server.MapPath("~/uploads/output/" + FileName)));
string FullxmlString = File.ReadAllText(Path.Combine(HttpContext.Current.Server.MapPath("~/uploads/output/" + FileName)));
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("payloadFile") { FileName = "payloadFile" };
multipartFormDataContent.Add(fileContent);
HttpResponseMessage response = client.PostAsync("api/message", multipartFormDataContent).Result;
string returnString = response.Content.ToString();
using (HttpContent content = response.Content)
{
string res = "";
Task<string> result = content.ReadAsStringAsync();
res = result.Result;
}
}
}