I'm trying to upload an image to Azure storage container.
Using UploadBlobWithRestAPI, I'm trying to call the rest PUT API and using AuthorizationHeader, I'm trying to create the Authorization for the API call.
I'm getting the image created in the container. But, for some reason the image is not in the readable format. On downloading the image from container and trying to open in explorer, am getting "It appears that we don't support this file format". Any idea?
public void UploadBlobWithRestAPI(string MachineName,string ImageName)
{
string storageKey = "Storagekey";
string storageAccount = "Account";
string containerName = "test-container";
string blobName = "test2.jpg";
string method = "PUT";
Byte[] imageContentBytes = System.IO.File.ReadAllBytes(#"C:\\Test2.jpg");
int imageContentLength = (Encoding.UTF8.GetString(imageContentBytes)).Length;
string requestUri = $"https://{storageAccount}.blob.core.windows.net/{containerName}/{blobName}";
System.Net.HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUri);
string now = DateTime.UtcNow.ToString("R");
request.Method = method;
request.ContentType = "application/octet-stream";
request.ContentLength = imageContentLength;
request.Headers.Add("x-ms-version", "2015-12-11");
request.Headers.Add("x-ms-date", now);
request.Headers.Add("x-ms-blob-type", "BlockBlob");
request.Headers.Add("Authorization", AuthorizationHeader(method, now, request, storageAccount, storageKey, containerName, blobName));
using (Stream requestStream = request.GetRequestStream())
{
requestStream.Write(Encoding.UTF8.GetBytes(Encoding.UTF8.GetString(imageContentBytes)), 0, imageContentLength);
}
using (HttpWebResponse resp = (HttpWebResponse)request.GetResponse())
{
MessageBox.Show(resp.StatusCode.ToString());
}
}
public string AuthorizationHeader(string method, string now, HttpWebRequest request, string storageAccount, string storageKey, string containerName, string blobName)
{
string headerResource = $"x-ms-blob-type:BlockBlob\nx-ms-date:{now}\nx-ms-version:2015-12-11";
string urlResource = $"/{storageAccount}/{containerName}/{blobName}";
string stringToSign = $"{method}\n\n\n{request.ContentLength}\n\n{request.ContentType}\n\n\n\n\n\n\n{headerResource}\n{urlResource}";
HMACSHA256 hmac = new HMACSHA256(Convert.FromBase64String(storageKey));
string signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)));
String AuthorizationHeader = String.Format("{0} {1}:{2}", "SharedKey", storageAccount, signature);
return AuthorizationHeader;
}
I believe the issue is coming because you are uploading an image (which is binary content) as a string which is corrupting the data.
Please try by changing the following:
int imageContentLength = (Encoding.UTF8.GetString(imageContentBytes)).Length;
to
int imageContentLength = imageContentBytes.Length;
and
using (Stream requestStream = request.GetRequestStream())
{
requestStream.Write(Encoding.UTF8.GetBytes(Encoding.UTF8.GetString(imageContentBytes)), 0, imageContentLength);
}
to
using (Stream requestStream = request.GetRequestStream())
{
requestStream.Write(imageContentBytes, 0, imageContentLength);
}
Also, please set the proper value for content type. Considering the file you are uploading is a JPEG image, please set the content type to image/jpeg instead of application/octet-stream. This will ensure that the image will be displayed correctly when loaded in a browser.
Related
I'm trying to simply upload an image file to Azure blob store and the file is making it there but the file size is bigger than it should be and when I download the file via the browser it won't open as an image.
I manually uploaded the same file via the Azure interface and the file works and is 22k, uploading via my code is 29k and doesn't work.
NOTE: One thing to note is that all the examples used with this code only send text files. Maybe the Encoding.UTF8.GetBytes(requestBody); line is doing it?
This is where I'm Base64 encoding my data
HttpPostedFileBase hpf = Request.Files[file] as HttpPostedFileBase
byte[] binData;
using (BinaryReader b = new BinaryReader(hpf.InputStream))
binData = b.ReadBytes(hpf.ContentLength);
var result = System.Convert.ToBase64String(binData);
new BlobHelper("STORENAMEHERE", "SECRETKEY").PutBlob("images", "test.jpg", result);
This is what I'm using to PUT the data, it's from https://azurestoragesamples.codeplex.com/
public bool PutBlob(string container, string blob, string content)
{
return Retry<bool>(delegate()
{
HttpWebResponse response;
try
{
SortedList<string, string> headers = new SortedList<string, string>();
headers.Add("x-ms-blob-type", "BlockBlob");
response = CreateRESTRequest("PUT", container + "/" + blob, content, headers).GetResponse() as HttpWebResponse;
response.Close();
return true;
}
catch (WebException ex)
{
if (ex.Status == WebExceptionStatus.ProtocolError &&
ex.Response != null &&
(int)(ex.Response as HttpWebResponse).StatusCode == 409)
return false;
throw;
}
});
}
public HttpWebRequest CreateRESTRequest(string method, string resource, string requestBody = null, SortedList<string, string> headers = null,
string ifMatch = "", string md5 = "")
{
byte[] byteArray = null;
DateTime now = DateTime.UtcNow;
string uri = Endpoint + resource;
HttpWebRequest request = HttpWebRequest.Create(uri) as HttpWebRequest;
request.Method = method;
request.ContentLength = 0;
request.Headers.Add("x-ms-date", now.ToString("R", System.Globalization.CultureInfo.InvariantCulture));
request.Headers.Add("x-ms-version", "2009-09-19");
if (headers != null)
{
foreach (KeyValuePair<string, string> header in headers)
request.Headers.Add(header.Key, header.Value);
}
if (!String.IsNullOrEmpty(requestBody))
{
request.Headers.Add("Accept-Charset", "UTF-8");
byteArray = Encoding.UTF8.GetBytes(requestBody);
request.ContentLength = byteArray.Length;
}
request.Headers.Add("Authorization", AuthorizationHeader(method, now, request, ifMatch, md5));
if (!String.IsNullOrEmpty(requestBody))
request.GetRequestStream().Write(byteArray, 0, byteArray.Length);
return request;
}
I believe the problem is with how you're converting the binary data to string and then converting it back to byte array.
While converting binary data to string, you're using System.Convert.ToBase64String however while getting the byte array from string you're using Encoding.UTF8.GetBytes. Most likely this is causing the mismatch.
Please change the following line of code:
byteArray = Encoding.UTF8.GetBytes(requestBody);
to
byteArray = System.Convert.FromBase64String(requestBody);
and that should fix the problem.
I am trying to get cognos report using siteminder token, below is my code.
string cognosUrl = "https://cognos.blah.com";
string reportPath = "/c10/cgi-bin/cognosisapi.dll/rds/reportData/report/"; string reportId = "ildjfsldkf"; //prod
cognosUrl += string.Concat(reportPath, reportId,"?blahblah");
string targetUrl = cognosUrl;
string strFormvalues = string.Concat("TARGET=",targetUrl);
ASCIIEncoding encoder = new ASCIIEncoding();
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(targetUrl);
byte[] data = encoder.GetBytes(strFormvalues);
request.AllowAutoRedirect = false;
request.Timeout = 120000;
request.ContentLength = data.Length;
request.ContentType = "text/xml;charset=\"utf-8\"";
request.Method = "POST";
request.Headers.Add(HttpRequestHeader.Cookie,"SMSESSION="+stoken);
request.GetRequestStream().Write(data, 0, data.Length);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream dataStream = response.GetResponseStream();
StreamReader reader = new StreamReader(dataStream);
string json = reader.ReadToEnd();
byte[] byteArray = Encoding.UTF8.GetBytes(json);
MemoryStream restream = new MemoryStream(byteArray);
using (Stream output = File.OpenWrite(#"c:\\Projects\\Test_"+DateTime.Now.ToString("yyyyMMddHHmmssfff")+".txt"))
using (Stream input = restream)
{
if (input != null) input.CopyTo(output);
}
// var results = serializer.DeserializeObject(json);
reader.Close();
dataStream.Close();
response.Close();
But I am getting response as " DPR-ERR-2101 Your request was invalid.Please contact your administrator."
I am not using C# myself, but a few recommendations while debugging this:
If you are only posting a URL, why not use GET instead of POST?
Try paste the targetURL in your browser, see what happens.
In my setup, when I paste the URL in the browser, I am always redirected before I receive an answer. (to a URL like, /cgi-bin/cognosisapi.dll/rds/sessionOutput/conversationID/i292ED29A62474697AD44306A388F5BBB You are preventing that to happen, that might be an issue)
Hope that helps.
I am trying to upload an image programmatically via an API to another server. The API expects me to upload image in a byte array to be sent in a field: "image_content".
My implementation and calling code is as below. The web request hits the server but the server responds that the image is not present in my web request.
When I run the below code, I am getting error that the image is not present in the request. What am I missing here?
public static class FormUpload
{
private static readonly Encoding encoding = Encoding.UTF8;
public static HttpWebResponse MultipartFormDataPost(string postUrl, string userAgent, Dictionary<string, object> postParameters)
{
string formDataBoundary = String.Format("----------{0:N}", Guid.NewGuid());
string contentType = "multipart/form-data; boundary=" + formDataBoundary;
byte[] formData = GetMultipartFormData(postParameters, formDataBoundary);
return PostForm(postUrl, userAgent, contentType, formData);
}
private static HttpWebResponse PostForm(string postUrl, string userAgent, string contentType, byte[] formData)
{
HttpWebRequest request = WebRequest.Create(postUrl) as HttpWebRequest;
if (request == null)
{
throw new NullReferenceException("request is not a http request");
}
// Set up the request properties.
request.Method = "POST";
request.ContentType = contentType;
request.UserAgent = userAgent;
request.ContentLength = formData.Length;
// Send the form data to the request.
using (Stream requestStream = request.GetRequestStream())
{
requestStream.Write(formData, 0, formData.Length);
requestStream.Close();
}
return request.GetResponse() as HttpWebResponse;
}
private static byte[] GetMultipartFormData(Dictionary<string, object> postParameters, string boundary)
{
Stream formDataStream = new System.IO.MemoryStream();
bool needsCLRF = false;
foreach (var param in postParameters)
{
if (param.Value is FileParameter)
{
FileParameter fileToUpload = (FileParameter)param.Value;
// Add just the first part of this param, since we will write the file data directly to the Stream
string header = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"; filename=\"{2}\"\r\nContent-Type: {3}\r\n\r\n",
boundary,
param.Key,
fileToUpload.FileName ?? param.Key,
fileToUpload.ContentType ?? "application/octet-stream");
formDataStream.Write(encoding.GetBytes(header), 0, encoding.GetByteCount(header));
// Write the file data directly to the Stream, rather than serializing it to a string.
formDataStream.Write(fileToUpload.File, 0, fileToUpload.File.Length);
}
else
{
string postData = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"\r\n\r\n{2}",
boundary,
param.Key,
param.Value);
formDataStream.Write(encoding.GetBytes(postData), 0, encoding.GetByteCount(postData));
}
}
// Add the end of the request. Start with a newline
string footer = "\r\n--" + boundary + "--\r\n";
formDataStream.Write(encoding.GetBytes(footer), 0, encoding.GetByteCount(footer));
// Dump the Stream into a byte[]
formDataStream.Position = 0;
byte[] formData = new byte[formDataStream.Length];
formDataStream.Read(formData, 0, formData.Length);
formDataStream.Close();
return formData;
}
public class FileParameter
{
public byte[] File { get; set; }
public string FileName { get; set; }
public string ContentType { get; set; }
public FileParameter(byte[] file) : this(file, null) { }
public FileParameter(byte[] file, string filename) : this(file, filename, null) { }
public FileParameter(byte[] file, string filename, string contenttype)
{
File = file;
FileName = filename;
ContentType = contenttype;
}
}
}
The code to call above function is:
// Read file data
FileStream fs = new FileStream("c:\\myimage.jpeg", FileMode.Open, FileAccess.Read);
byte[] data = new byte[fs.Length];
fs.Read(data, 0, data.Length);
fs.Close();
// Generate post objects
Dictionary<string, object> postParameters = new Dictionary<string, object>();
postParameters.Add("image_content",data);
// Create request and receive response
string postURL = "myurl";
string userAgent = "Mozilla";
HttpWebResponse webResponse = FormUpload.MultipartFormDataPost(postURL, userAgent, postParameters);
// Process response
StreamReader responseReader = new StreamReader(webResponse.GetResponseStream());
string fullResponse = responseReader.ReadToEnd();
webResponse.Close();
Response.Write(fullResponse);
In my opinion, you should use the MultipartFormDataContent class because it "Provides a container for content encoded using multipart/form-data MIME type.". Try this
public static HttpWebResponse MultipartFormDataPost(string postUrl, string userAgent, byte[] data)
{
string contentType;
byte[] formData = Program.GetMultipartFormData(data, out contentType);
return PostForm(postUrl, userAgent, contentType, formData);
}
public static byte[] GetMultipartFormData(byte[] data, out string contentType)
{
var byteArrayContent = new ByteArrayContent(data);
byteArrayContent.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
byteArrayContent.Headers.Add("image_content", "myimage.jpeg");
var content = new MultipartFormDataContent(String.Format("----------{0:N}", Guid.NewGuid())) { byteArrayContent };
contentType = content.Headers.ContentType.ToString();
return content.ReadAsByteArrayAsync().Result;
}
I was able to resolve the problem by the use of RestSharp Api mentioned in the stackoverflow question Upload file through c# using JSON request and RestSharp.
You all code is fine but you forgot To encode you parameter
try this
string postData = string.Format("--{0}\r\nContent-Disposition:
form-data; name=\"{1}\"\r\n\r\n{2}",
boundary,
HttpUtility.UrlEncode(param.Key),
HttpUtility.UrlEncode(param.Value));
In case of binary data
HttpUtility.UrlEncode(Convert.ToBase64String(byte[]))
try to use this code to add parameter in your request
NameValueCollection outgoingQueryString = HttpUtility.ParseQueryString(String.Empty);
outgoingQueryString.Add("uname", "username");
outgoingQueryString.Add("pname", "password");
string postdata = outgoingQueryString.ToString();
and write this postdata in you request
I'm trying to upload a file with ftp in C#. for the moment, i try to do it locally:
static void Main(string[] args)
{
UploadFileToFtp("C:\\Utilisateurs\\arnaud\\Bureau\\yhyhyyh.rtf","root","root");
}
public static void UploadFileToFtp(string filePath, string username, string password)
{
var fileName = Path.GetFileName(filePath);
var request = (FtpWebRequest)WebRequest.Create("127.0.0.1/" + fileName);<---ERROR
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Credentials = new NetworkCredential(username, password);
request.UsePassive = true;
request.UseBinary = true;
request.KeepAlive = false;
using (var fileStream = File.OpenRead(filePath))
{
using (var requestStream = request.GetRequestStream())
{
fileStream.CopyTo(requestStream);
requestStream.Close();
}
}
var response = (FtpWebResponse)request.GetResponse();
Console.WriteLine("Upload done: {0}", response.StatusDescription);
response.Close();
}
I get the following error: (see above)
The format of the URI could not be determined
Thanks for your help
I think you are missing protocol: should be ftp://127.0.0.1/ instead of 127.0.0.1/. What's more, I suggest you to encode part of url that is stored in filePath. f.e:
var encoded = HttpUtility.UrlEncode(filePath);
var request = (FtpWebRequest)WebRequest.Create("ftp://127.0.0.1/" + encoded)
You need to reference System.Web assembly to use UrlEncode. More here.
I am using 4shared rest api, and working on edit file information by http put. I coded like this:
public void UpdateFile(string fileID, string accessToken, int uniqueID)
{
Action<string> OnResponse = this.OnFileUpdate;
string uri = string.Format("http://api.4shared.com/v0/files/fileID.json?oauth_token= {1}&UniqueID={2}",accessToken,uniquesID);
uri=uri + "&name=mayank&description=This is for testing.";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri(uri));
request.Method = "PUT";
request.ContentType = "application/x-www-form-urlencoded";
request.BeginGetResponse(delegate(IAsyncResult result)
{
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result);
using (var stream = response.GetResponseStream())
{
using (StreamReader reader = new StreamReader(stream))
{
string response1 = reader.ReadToEnd();
onResponseGot(response1);
}
}
}, null);
}
private void OnFileUpdate(string result)
{
if (!string.IsNullOrEmpty(result))
{
//do some code after file updates.
}
}
Now I am getting response but with same old values. I also tried to test it on api console but result is same. I didn't find out the problem.