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());
}
Does anyone know how to use the HttpClient in .Net 4.5 with multipart/form-data upload?
I couldn't find any examples on the internet.
my result looks like this:
public static async Task<string> Upload(byte[] image)
{
using (var client = new HttpClient())
{
using (var content =
new MultipartFormDataContent("Upload----" + DateTime.Now.ToString(CultureInfo.InvariantCulture)))
{
content.Add(new StreamContent(new MemoryStream(image)), "bilddatei", "upload.jpg");
using (
var message =
await client.PostAsync("http://www.directupload.net/index.php?mode=upload", content))
{
var input = await message.Content.ReadAsStringAsync();
return !string.IsNullOrWhiteSpace(input) ? Regex.Match(input, #"http://\w*\.directupload\.net/images/\d*/\w*\.[a-z]{3}").Value : null;
}
}
}
}
It works more or less like this (example using an image/jpg file):
async public Task<HttpResponseMessage> UploadImage(string url, byte[] ImageData)
{
var requestContent = new MultipartFormDataContent();
// here you can specify boundary if you need---^
var imageContent = new ByteArrayContent(ImageData);
imageContent.Headers.ContentType =
MediaTypeHeaderValue.Parse("image/jpeg");
requestContent.Add(imageContent, "image", "image.jpg");
return await client.PostAsync(url, requestContent);
}
(You can requestContent.Add() whatever you want, take a look at the HttpContent descendant to see available types to pass in)
When completed, you'll find the response content inside HttpResponseMessage.Content that you can consume with HttpContent.ReadAs*Async.
This is an example of how to post string and file stream with HTTPClient using MultipartFormDataContent. The Content-Disposition and Content-Type need to be specified for each HTTPContent:
Here's my example. Hope it helps:
private static void Upload()
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("User-Agent", "CBS Brightcove API Service");
using (var content = new MultipartFormDataContent())
{
var path = #"C:\B2BAssetRoot\files\596086\596086.1.mp4";
string assetName = Path.GetFileName(path);
var request = new HTTPBrightCoveRequest()
{
Method = "create_video",
Parameters = new Params()
{
CreateMultipleRenditions = "true",
EncodeTo = EncodeTo.Mp4.ToString().ToUpper(),
Token = "x8sLalfXacgn-4CzhTBm7uaCxVAPjvKqTf1oXpwLVYYoCkejZUsYtg..",
Video = new Video()
{
Name = assetName,
ReferenceId = Guid.NewGuid().ToString(),
ShortDescription = assetName
}
}
};
//Content-Disposition: form-data; name="json"
var stringContent = new StringContent(JsonConvert.SerializeObject(request));
stringContent.Headers.Add("Content-Disposition", "form-data; name=\"json\"");
content.Add(stringContent, "json");
FileStream fs = File.OpenRead(path);
var streamContent = new StreamContent(fs);
streamContent.Headers.Add("Content-Type", "application/octet-stream");
//Content-Disposition: form-data; name="file"; filename="C:\B2BAssetRoot\files\596090\596090.1.mp4";
streamContent.Headers.Add("Content-Disposition", "form-data; name=\"file\"; filename=\"" + Path.GetFileName(path) + "\"");
content.Add(streamContent, "file", Path.GetFileName(path));
//content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
Task<HttpResponseMessage> message = client.PostAsync("http://api.brightcove.com/services/post", content);
var input = message.Result.Content.ReadAsStringAsync();
Console.WriteLine(input.Result);
Console.Read();
}
}
}
Try this its working for me.
private static async Task<object> Upload(string actionUrl)
{
Image newImage = Image.FromFile(#"Absolute Path of image");
ImageConverter _imageConverter = new ImageConverter();
byte[] paramFileStream= (byte[])_imageConverter.ConvertTo(newImage, typeof(byte[]));
var formContent = new MultipartFormDataContent
{
// Send form text values here
{new StringContent("value1"),"key1"},
{new StringContent("value2"),"key2" },
// Send Image Here
{new StreamContent(new MemoryStream(paramFileStream)),"imagekey","filename.jpg"}
};
var myHttpClient = new HttpClient();
var response = await myHttpClient.PostAsync(actionUrl.ToString(), formContent);
string stringContent = await response.Content.ReadAsStringAsync();
return response;
}
Here is another example on how to use HttpClient to upload a multipart/form-data.
It uploads a file to a REST API and includes the file itself (e.g. a JPG) and additional API parameters. The file is directly uploaded from local disk via FileStream.
See here for the full example including additional API specific logic.
public static async Task UploadFileAsync(string token, string path, string channels)
{
// we need to send a request with multipart/form-data
var multiForm = new MultipartFormDataContent();
// add API method parameters
multiForm.Add(new StringContent(token), "token");
multiForm.Add(new StringContent(channels), "channels");
// add file and directly upload it
FileStream fs = File.OpenRead(path);
multiForm.Add(new StreamContent(fs), "file", Path.GetFileName(path));
// send request to API
var url = "https://slack.com/api/files.upload";
var response = await client.PostAsync(url, multiForm);
}
Here's a complete sample that worked for me. The boundary value in the request is added automatically by .NET.
var url = "http://localhost/api/v1/yourendpointhere";
var filePath = #"C:\path\to\image.jpg";
HttpClient httpClient = new HttpClient();
MultipartFormDataContent form = new MultipartFormDataContent();
FileStream fs = File.OpenRead(filePath);
var streamContent = new StreamContent(fs);
var imageContent = new ByteArrayContent(streamContent.ReadAsByteArrayAsync().Result);
imageContent.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/form-data");
form.Add(imageContent, "image", Path.GetFileName(filePath));
var response = httpClient.PostAsync(url, form).Result;
Example with preloader Dotnet 3.0 Core
ProgressMessageHandler processMessageHander = new ProgressMessageHandler();
processMessageHander.HttpSendProgress += (s, e) =>
{
if (e.ProgressPercentage > 0)
{
ProgressPercentage = e.ProgressPercentage;
TotalBytes = e.TotalBytes;
progressAction?.Invoke(progressFile);
}
};
using (var client = HttpClientFactory.Create(processMessageHander))
{
var uri = new Uri(transfer.BackEndUrl);
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", AccessToken);
using (MultipartFormDataContent multiForm = new MultipartFormDataContent())
{
multiForm.Add(new StringContent(FileId), "FileId");
multiForm.Add(new StringContent(FileName), "FileName");
string hash = "";
using (MD5 md5Hash = MD5.Create())
{
var sb = new StringBuilder();
foreach (var data in md5Hash.ComputeHash(File.ReadAllBytes(FullName)))
{
sb.Append(data.ToString("x2"));
}
hash = result.ToString();
}
multiForm.Add(new StringContent(hash), "Hash");
using (FileStream fs = File.OpenRead(FullName))
{
multiForm.Add(new StreamContent(fs), "file", Path.GetFileName(FullName));
var response = await client.PostAsync(uri, multiForm);
progressFile.Message = response.ToString();
if (response.IsSuccessStatusCode) {
progressAction?.Invoke(progressFile);
} else {
progressErrorAction?.Invoke(progressFile);
}
response.EnsureSuccessStatusCode();
}
}
}
I'm adding a code snippet which shows on how to post a file to an API which has been exposed over DELETE http verb. This is not a common case to upload a file with DELETE http verb but it is allowed. I've assumed Windows NTLM authentication for authorizing the call.
The problem that one might face is that all the overloads of HttpClient.DeleteAsync method have no parameters for HttpContent the way we get it in PostAsync method
var requestUri = new Uri("http://UrlOfTheApi");
using (var streamToPost = new MemoryStream("C:\temp.txt"))
using (var fileStreamContent = new StreamContent(streamToPost))
using (var httpClientHandler = new HttpClientHandler() { UseDefaultCredentials = true })
using (var httpClient = new HttpClient(httpClientHandler, true))
using (var requestMessage = new HttpRequestMessage(HttpMethod.Delete, requestUri))
using (var formDataContent = new MultipartFormDataContent())
{
formDataContent.Add(fileStreamContent, "myFile", "temp.txt");
requestMessage.Content = formDataContent;
var response = httpClient.SendAsync(requestMessage).GetAwaiter().GetResult();
if (response.IsSuccessStatusCode)
{
// File upload was successfull
}
else
{
var erroResult = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
throw new Exception("Error on the server : " + erroResult);
}
}
You need below namespaces at the top of your C# file:
using System;
using System.Net;
using System.IO;
using System.Net.Http;
P.S. You are seeing a number of using blocks(IDisposable pattern) in the above code snippet which doesn't look very clean. Unfortunately, the syntax of using construct doesn't support initializing multiple variables in single statement.
X509Certificate clientKey1 = null;
clientKey1 = new X509Certificate(AppSetting["certificatePath"],
AppSetting["pswd"]);
string url = "https://EndPointAddress";
FileStream fs = File.OpenRead(FilePath);
var streamContent = new StreamContent(fs);
var FileContent = new ByteArrayContent(streamContent.ReadAsByteArrayAsync().Result);
FileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("ContentType");
var handler = new WebRequestHandler();
handler.ClientCertificateOptions = ClientCertificateOption.Manual;
handler.ClientCertificates.Add(clientKey1);
handler.ServerCertificateValidationCallback = (httpRequestMessage, cert, cetChain, policyErrors) =>
{
return true;
};
using (var client = new HttpClient(handler))
{
// Post it
HttpResponseMessage httpResponseMessage = client.PostAsync(url, FileContent).Result;
if (!httpResponseMessage.IsSuccessStatusCode)
{
string ss = httpResponseMessage.StatusCode.ToString();
}
}
public async Task<object> PassImageWithText(IFormFile files)
{
byte[] data;
string result = "";
ByteArrayContent bytes;
MultipartFormDataContent multiForm = new MultipartFormDataContent();
try
{
using (var client = new HttpClient())
{
using (var br = new BinaryReader(files.OpenReadStream()))
{
data = br.ReadBytes((int)files.OpenReadStream().Length);
}
bytes = new ByteArrayContent(data);
multiForm.Add(bytes, "files", files.FileName);
multiForm.Add(new StringContent("value1"), "key1");
multiForm.Add(new StringContent("value2"), "key2");
var res = await client.PostAsync(_MEDIA_ADD_IMG_URL, multiForm);
}
}
catch (Exception e)
{
throw new Exception(e.ToString());
}
return result;
}
I create a bot (#mp3lyric_bot_test) in telegram and set it as administrator in my channel (#mp3lyric_test). Now I want to make a request to send an mp3 to channel using telegram api.
my mp3 is in web, something like this: http://bayanbox.ir/download/7028444634071302239/Sound-1.mp3
At first i download mp3 with this method:
public static Task<byte[]> DownloadAsync(string requestUriSt)
{
var requestUri = new Uri(requestUriSt);
byte[] fileBytes;
using (var httpClient = new HttpClient())
{
using (var request = new HttpRequestMessage(HttpMethod.Get, requestUri))
{
using (var responseMessage = await httpClient.SendAsync(request))
{
fileBytes = await responseMessage.Content.ReadAsByteArrayAsync();
var audioString = Encoding.UTF8.GetString(fileBytes, 0, fileBytes.Length);
}
}
}
return fileBytes;
}
if there is a way to send mp3 directly without download, please tell me how? thanks.
Then send that byte array (fileBytes) using this code:
my bot token is 247655935:AAEhpYCeoXA5y7V8Z3WrVcNJ3AaChORjfvw
using (var client = new HttpClient())
{
var uri = new Uri("https://api.telegram.org/bot247655935:AAEhpYCeoXA5y7V8Z3WrVcNJ3AaChORjfvw/sendAudio");
using (var multipartFormDataContent = new MultipartFormDataContent(
"SendAudio----" + DateTime.Now.ToString(CultureInfo.InvariantCulture)))
{
multipartFormDataContent.Add(
new StringContent("#mp3lyric_test"),
string.Format("\"{0}\"", "chat_id")
);
multipartFormDataContent.Add(
new StreamContent(new MemoryStream(fileBytes)),
'"' + "audio" + '"'
);
using (var message = await client.PostAsync(uri, multipartFormDataContent))
{
var contentString = await message.Content.ReadAsStringAsync();
}
}
}
I have two error:
"Request Entity Too Large" when my mp3 is about 6mb or 7mb or ... (not using http://bayanbox.ir/download/7028444634071302239/Sound-1.mp3)
error_code:400, description:"Bad Request: URL must be in UTF-8" (after using that mp3 for test that is 28kb)
To send a new AudioFile you use the SendAudio method but with the InputFile field.
First create an InputFile object, then pass those bytes in the audio parameter of the SendAudio method
If you need to resend the same AudioFile to another user, then you can use the String option as the audio parameter in the SendAudio
I chaged my codes for send the byte array (fileBytes) and now it works:
using (var client = new HttpClient())
{
var uri = new Uri("https://api.telegram.org/bot247655935:AAEhpYCeoXA5y7V8Z3WrVcNJ3AaChORjfvw/sendAudio?chat_id=#mp3lyric_test");
using (var multipartFormDataContent = new MultipartFormDataContent())
{
var streamContent = new StreamContent(new MemoryStream(fileBytes));
streamContent.Headers.Add("Content-Type", "application/octet-stream");
streamContent.Headers.Add("Content-Disposition", "form-data; name=\"audio\"; filename=\"Sound-1.mp3\"");
multipartFormDataContent.Add(streamContent, "file", "Sound-1.mp3");
using (var message = await client.PostAsync(uri, multipartFormDataContent))
{
var contentString = await message.Content.ReadAsStringAsync();
}
}
}
I need create POST request from WinRT app,which should contain StorageFile.
I need to do this exactly in style like this : post request with file inside body.
Is it possible? I know about HttpClient.PostAsync(..), but I can't put StorageFile inside request body. I want to send mp3 file to Web Api
On server side I get file like this:
[System.Web.Http.HttpPost]
public HttpResponseMessage UploadRecord([FromUri]string filename)
{
HttpResponseMessage result = null;
var httpRequest = HttpContext.Current.Request;
if (httpRequest.Files.Count > 0)
{
foreach (string file in httpRequest.Files)
{
var postedFile = httpRequest.Files[file];
var filePath = HttpContext.Current.Server.MapPath("~/Audio/" + filename + ".mp3");
postedFile.SaveAs(filePath);
}
result = Request.CreateResponse(HttpStatusCode.Created);
}
else
{
result = Request.CreateResponse(HttpStatusCode.BadRequest);
}
return result;
}
You can send it as a byte[] using the ByteArrayContent class as a second parameter:
StroageFile file = // Get file here..
byte[] fileBytes = null;
using (IRandomAccessStreamWithContentType stream = await file.OpenReadAsync())
{
fileBytes = new byte[stream.Size];
using (DataReader reader = new DataReader(stream))
{
await reader.LoadAsync((uint)stream.Size);
reader.ReadBytes(fileBytes);
}
}
var httpClient = new HttpClient();
var byteArrayContent = new ByteArrayContent(fileBytes);
await httpClient.PostAsync(address, fileBytes);
If you're uploading files of any appreciable size, then it's best to use the Background Transfer API so that the upload doesn't get paused if the app is suspended. Specifically see BackgroundUploader.CreateUpload which takes a StorageFile directly. Refer to the Background Transfer sample for both the client and server sides of this relationship, as the sample also includes a sample server.
To use less memory you can pipe the file stream to the HttpClient stream directly.
public async Task UploadBinaryAsync(Uri uri)
{
var openPicker = new FileOpenPicker();
StorageFile file = await openPicker.PickSingleFileAsync();
if (file == null)
return;
using (IRandomAccessStreamWithContentType fileStream = await file.OpenReadAsync())
using (var client = new HttpClient())
{
try
{
var content = new HttpStreamContent(fileStream);
content.Headers.ContentType =
new HttpMediaTypeHeaderValue("application/octet-stream");
HttpResponseMessage response = await client.PostAsync(uri, content);
_ = response.EnsureSuccessStatusCode();
}
catch (Exception ex)
{
// Handle exceptions appropriately
}
}
}
I need some help for posting a MultipartFormDataContentto my web service.
I have an error 500 but I didn't know why.
There is a mean to see what kind of data i send with visual studio? Or there is a mistake in my code?
My c# code Client
using (var client = new HttpClient())
{
using (var content =
new MultipartFormDataContent())
{
MemoryStream s = new MemoryStream();
StreamWriter writer = new StreamWriter(s);
writer.Write(json);
writer.Flush();
s.Position = 0;
content.Add(new StreamContent(s), "JSON");
foreach (KeyValuePair<String, byte[]> pair in data)
{
Stream stream = new MemoryStream(pair.Value);
content.Add(new StreamContent(stream),"uploaded");
}
using (
var message =
await client.PostAsync(urlFinal, content))
{
var input = await message.Content.ReadAsStringAsync();
}
}
}
And the Web Service part in JAVA
public static Result Method() {
MultipartFormData data = request().body().asMultipartFormData();
return ok(toJson(MyObject.myMethode(data)));
}
public static int myMethode(MultipartFormData data) {
FilePart JSON = data.getFile("JSON");
FilePart picture = data.getFile("uploaded");
return 1;
}