Uploading image to imgur causes: The Uri string is too long - c#

im trying to develope C# application that uses Imgur api to upload images.
this is my upload function:
public static string PostToImgur(string imagFilePath, string apiKey)
{
byte[] imageData;
FileStream fileStream = File.OpenRead(imagFilePath);
imageData = new byte[fileStream.Length];
fileStream.Read(imageData, 0, imageData.Length);
fileStream.Close();
string uploadRequestString = "image=" + Uri.EscapeDataString(System.Convert.ToBase64String(imageData)) + "&key=" + apiKey;
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create("https://api.imgur.com/3/image");
webRequest.Method = "POST";
webRequest.ContentType = "application/x-www-form-urlencoded";
webRequest.ServicePoint.Expect100Continue = false;
webRequest.Headers["Authorization"] = "Client-ID abd937cc5e11dc9";
StreamWriter streamWriter = new StreamWriter(webRequest.GetRequestStream());
streamWriter.Write(uploadRequestString);
streamWriter.Close();
WebResponse response = webRequest.GetResponse();
Stream responseStream = response.GetResponseStream();
StreamReader responseReader = new StreamReader(responseStream);
return responseReader.ReadToEnd();
}
if im uploading small pictures (20kb) all works fine.
but when im uploding bigger images (500kb) i get the error:
Invalid URI: The Uri string is too long.
what can i do?

i succeed to upload large images by dividing the base64 string
this is the working code:
public static string PostToImgur(string imagFilePath, string apiKey)
{
byte[] imageData;
FileStream fileStream = File.OpenRead(imagFilePath);
imageData = new byte[fileStream.Length];
fileStream.Read(imageData, 0, imageData.Length);
fileStream.Close();
const int MAX_URI_LENGTH = 32766;
string base64img = System.Convert.ToBase64String(imageData);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < base64img.Length; i += MAX_URI_LENGTH)
{
sb.Append(Uri.EscapeDataString(base64img.Substring(i, Math.Min(MAX_URI_LENGTH, base64img.Length - i))));
}
string uploadRequestString = "key=" + apiKey + "&title=" + "imageTitle" +
"&caption=" + "img" + "&image=" + sb.ToString();
// string uploadRequestString = "image=" + Uri.EscapeDataString(System.Convert.ToBase64String(imageData)) + "&key=" + apiKey;
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create("https://api.imgur.com/3/image");
webRequest.Method = "POST";
webRequest.ContentType = "application/x-www-form-urlencoded";
webRequest.ServicePoint.Expect100Continue = false;
webRequest.Headers["Authorization"] = "Client-ID abd937cc5e11dc9";
StreamWriter streamWriter = new StreamWriter(webRequest.GetRequestStream());
streamWriter.Write(uploadRequestString);
streamWriter.Close();
WebResponse response = webRequest.GetResponse();
Stream responseStream = response.GetResponseStream();
StreamReader responseReader = new StreamReader(responseStream);
return responseReader.ReadToEnd();
}
thanks to all.

They way it works is the image is converted like so: System.Convert.ToBase64String(imageData)
That is added to the URI and sent to the server to be decoded back to an image.
You will not be able to get around this issue with a single URI, as its inherent in imgur's design.
Read this for the maximum length a URI can be: What is the maximum length of a URL in different browsers?

Related

C# WebRequest POST and get a specific line - how to display it in label

here is the picture of it .. look here also /.. http://prntscr.com/5wadok
string fbid = stTextBox1.Text;
string ukey = stTextBox2.Text;
string jumlah = "4";
ASCIIEncoding encoding = new ASCIIEncoding();
string postData = "fbid=" + fbid + "&ukey=" + ukey + "&jumlah=" + jumlah; ;
byte[] data = encoding.GetBytes(postData);
WebRequest request = WebRequest.Create("http://dcvn-full.ga/test/dcgems.php");
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = data.Length;
Stream stream = request.GetRequestStream();
stream.Write(data, 0, data.Length);
stream.Close();
WebResponse response = request.GetResponse();
stream = response.GetResponseStream();
StreamReader sr = new StreamReader(stream);
//MessageBox.Show(sr.ReadToEnd());
stLabel4.Text = (sr.ReadLine());
sr.Close();
stream.Close();
I need to read the line21to25 and show it in the stlabel.5 with this command or any other , can u help me??
I modified your code as follows. Hopefully it will solve your problem.
string fbid = stTextBox1.Text;
string ukey = stTextBox2.Text;
string jumlah = "4";
ASCIIEncoding encoding = new ASCIIEncoding();
string postData = "fbid=" + fbid + "&ukey=" + ukey + "&jumlah=" + jumlah; ;
byte[] data = encoding.GetBytes(postData);
WebRequest request = WebRequest.Create("http://dcvn-full.ga/test/dcgems.php");
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = data.Length;
using (Stream stream = request.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
WebResponse response = request.GetResponse();
stream = response.GetResponseStream();
StringBuilder sb = new StringBuilder();
using (StreamReader sr = new StreamReader(stream))
{
int count=1;
while(sr.EndOfStream)
{
string line = sr.ReadLine();
if(count>=21 && count<=25)
{
sb.AppendLine(line);
}
count++;
if (count > 25)
break;
}
stLabel4.Text = (sb.ToString());
}

WebDAV get free space info

I'm working with Yandex Disk API (http://api.yandex.com/disk/doc/dg/reference/propfind_space-request.xml).
Having trouble with adding property in the request body (quota-available-bytes and quota-used-bytes)
public static string SpaceInfo(string path)
{
// Authorization.
HttpWebRequest webReq = (HttpWebRequest)WebRequest.Create("https://webdav.yandex.ru/");
webReq.Accept = "*/*";
webReq.Headers.Add("Depth: 0");
webReq.Headers.Add("Authorization: OAuth " + token);
webReq.Method = "PROPFIND";
// Adding data in body request.
string inputData = #"<D:propfind xmlns:D=""DAV:""><D:prop><quota-available-bytes/></D:prop></D:propfind>";
byte[] buffer = new ASCIIEncoding().GetBytes(inputData);
webReq.ContentType = "text/xml; encoding='utf-8";
webReq.ContentLength = buffer.Length;
try
{
HttpWebResponse resp = (HttpWebResponse)webReq.GetResponse();
StreamReader sr = new StreamReader(resp.GetResponseStream());
string dinfo = sr.ReadToEnd();
return dinfo;
}
}
I don't get any response, maybe i can use another method? What should i do?
Thanks!
quota-available-bytes should use same namespace "D"

How to get response from Base CRM API authentication

I am trying to get a response from Base API, but i keep getting "500 Internal Server Error" error. I want to get at least 401 HTTP Response which means that authentication call has failed. Here is a description of using Base API authentication:
http://dev.futuresimple.com/api/authentication
And here is my code:
public string Authenticate()
{
string result = "";
string url = "https://sales.futuresimple.com/api/v1/";
string email = "mail#mail.com";
string password = "pass";
string postData = "email=" + email + "&password=" + password;
HttpWebRequest request = null;
Uri uri = new Uri(url + "authentication.xml");
request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = "POST";
request.ContentType = "application/xml";
request.ContentLength = postData.Length;
using (Stream writeStream = request.GetRequestStream())
{
UTF8Encoding encoding = new UTF8Encoding();
byte[] bytes = encoding.GetBytes(postData);
writeStream.Write(bytes, 0, bytes.Length);
writeStream.Close();
}
try
{
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
using (Stream responseStream = response.GetResponseStream())
{
using (StreamReader readStream = new StreamReader(responseStream, Encoding.UTF8))
{
result = readStream.ReadToEnd();
}
}
}
}
catch (WebException ex)
{
ex = ex;
}
return result;
}
You're setting the ContentType to application/xml - this is the type of the request body. The body you're sending (string postData = "email=" + email + "&password=" + password;) is form-encoded instead of xml. Just skipping the line request.ContentType = "application/xml"; should do the trick. Alternatively you can encode your request body as xml.

Uploading files to Google Drive with non-ASCII letters in the titles

How can I upload a file to Google Drive if it contains non-ASCII symbols in
its title?
Currently I'm using this method to start the upload to Google Drive. But if I'm passing a filename which contains non-ASCII letters, it is fails returning ParseError in the JSON response.
public string startUploadSession(string mimeType, long fileLength, string filename)
{
string uri = "https://www.googleapis.com/upload/drive/v2/files?uploadType=resumable" + "&access_token=" + account.accessInfo.access_token;
var request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = "POST";
request.ContentType = "application/json; charset=utf-8";
request.Headers.Add("X-Upload-Content-Type", mimeType);
request.Headers.Add("X-Upload-Content-Length", fileLength.ToString());
// Here we're providing file metadata
File file = new File();
file.title = filename;
string requestBody = toJsonString(file);
request.ContentLength = requestBody.Length;
System.IO.Stream requestStream = request.GetRequestStream();
requestStream.Write(requestBody.ToByteArray(), 0, requestBody.Length);
requestStream.Close();
try
{
var response = request.GetResponse();
var reader = new System.IO.StreamReader(response.GetResponseStream());
var responseBody = reader.ReadToEnd();
return response.Headers["Location"];
}
catch (WebException ex)
{
System.IO.StreamReader reader = new System.IO.StreamReader(ex.Response.GetResponseStream());
string error = reader.ReadToEnd();
Logger.Error(error, "Getting upload uri");
return null;
}
}
OK. This is my bug. Fixed part of code:
System.IO.Stream requestStream = request.GetRequestStream();
byte[] utf8Bytes = requestBody.ToByteArray();
requestStream.Write(utf8Bytes, 0, utf8Bytes.Count());
requestStream.Close();

Posting image from .NET to Facebook wall using the Graph API

I'm using the Facebooks Javascript API to develop an application that will need to be able to post an image to a users wall.
That part of the app needs to be server-side as far as I can tell, since it needs to post the image data as "multipart/form-data".
Note: It's not the simple version using "post", but the real "photos" method.
http://graph.facebook.com/me/photos
I think I'm facing two problems, a .NET and a Facebook problem:
Facebook problem: I'm not quite sure if all parameters should be send as multipart/form-data (including the access_token and message). The only code example there is uses the cUrl util/application.
.NET problem: I have never issued multipart/form-data requests from .NET , and I'm not sure if .NET automatically creates the mime-parts, or if I have to encode the parameters in some special way.
It's a bit hard to debug, since the only error response I get from the Graph API is "400 - bad request".
Below is the code as it looked when I decided to write this question (yes, it's a bit verbose :-)
The ultimate answer would of course be a sample snippet posting an image from .NET, but I can settle for less.
string username = null;
string password = null;
int timeout = 5000;
string requestCharset = "UTF-8";
string responseCharset = "UTF-8";
string parameters = "";
string responseContent = "";
string finishedUrl = "https://graph.facebook.com/me/photos";
parameters = "access_token=" + facebookAccessToken + "&message=This+is+an+image";
HttpWebRequest request = null;
request = (HttpWebRequest)WebRequest.Create(finishedUrl);
request.Method = "POST";
request.KeepAlive = false;
//application/x-www-form-urlencoded | multipart/form-data
request.ContentType = "multipart/form-data";
request.Timeout = timeout;
request.AllowAutoRedirect = false;
if (username != null && username != "" && password != null && password != "")
{
request.PreAuthenticate = true;
request.Credentials = new NetworkCredential(username, password).GetCredential(new Uri(finishedUrl), "Basic");
}
//write parameters to request body
Stream requestBodyStream = request.GetRequestStream();
Encoding requestParameterEncoding = Encoding.GetEncoding(requestCharset);
byte[] parametersForBody = requestParameterEncoding.GetBytes(parameters);
requestBodyStream.Write(parametersForBody, 0, parametersForBody.Length);
/*
This wont work
byte[] startParm = requestParameterEncoding.GetBytes("&source=");
requestBodyStream.Write(startParm, 0, startParm.Length);
byte[] fileBytes = File.ReadAllBytes(Server.MapPath("images/sample.jpg"));
requestBodyStream.Write( fileBytes, 0, fileBytes.Length );
*/
requestBodyStream.Close();
HttpWebResponse response = null;
Stream receiveStream = null;
StreamReader readStream = null;
Encoding responseEncoding = System.Text.Encoding.GetEncoding(responseCharset);
try
{
response = (HttpWebResponse) request.GetResponse();
receiveStream = response.GetResponseStream();
readStream = new StreamReader( receiveStream, responseEncoding );
responseContent = readStream.ReadToEnd();
}
finally
{
if (receiveStream != null)
{
receiveStream.Close();
}
if (readStream != null)
{
readStream.Close();
}
if (response != null)
{
response.Close();
}
}
Here is a sample of how to upload binary data. But an uploading to /me/photos won't publish the image into wall :( The image saving into your app's album. I'm stuck on how to announce it in the feed. Yet another way is to post an image into "Wall Album", by URL=="graph.facebook.com/%wall-album-id%/photos". But didn't found any way to create sucha album (user creates it when uploading an image via the site).
{
string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
uploadRequest = (HttpWebRequest)WebRequest.Create(#"https://graph.facebook.com/me/photos");
uploadRequest.ServicePoint.Expect100Continue = false;
uploadRequest.Method = "POST";
uploadRequest.UserAgent = "Mozilla/4.0 (compatible; Windows NT)";
uploadRequest.ContentType = "multipart/form-data; boundary=" + boundary;
uploadRequest.KeepAlive = false;
StringBuilder sb = new StringBuilder();
string formdataTemplate = "--{0}\r\nContent-Disposition: form-data; name=\"{1}\"\r\n\r\n{2}\r\n";
sb.AppendFormat(formdataTemplate, boundary, "access_token", PercentEncode(facebookAccessToken));
sb.AppendFormat(formdataTemplate, boundary, "message", PercentEncode("This is an image"));
string headerTemplate = "--{0}\r\nContent-Disposition: form-data; name=\"{1}\"; filename=\"{2}\"\r\nContent-Type: {3}\r\n\r\n";
sb.AppendFormat(headerTemplate, boundary, "source", "file.png", #"application/octet-stream");
string formString = sb.ToString();
byte[] formBytes = Encoding.UTF8.GetBytes(formString);
byte[] trailingBytes = Encoding.UTF8.GetBytes("\r\n--" + boundary + "--\r\n");
long imageLength = imageMemoryStream.Length;
long contentLength = formBytes.Length + imageLength + trailingBytes.Length;
uploadRequest.ContentLength = contentLength;
uploadRequest.AllowWriteStreamBuffering = false;
Stream strm_out = uploadRequest.GetRequestStream();
strm_out.Write(formBytes, 0, formBytes.Length);
byte[] buffer = new Byte[checked((uint)Math.Min(4096, (int)imageLength))];
int bytesRead = 0;
int bytesTotal = 0;
imageMemoryStream.Seek(0, SeekOrigin.Begin);
while ((bytesRead = imageMemoryStream.Read(buffer, 0, buffer.Length)) != 0)
{
strm_out.Write(buffer, 0, bytesRead); bytesTotal += bytesRead;
gui.OnUploadProgress(this, (int)(bytesTotal * 100 / imageLength));
}
strm_out.Write(trailingBytes, 0, trailingBytes.Length);
strm_out.Close();
HttpWebResponse wresp = uploadRequest.GetResponse() as HttpWebResponse;
}
Cleaned up class method using #fitz's code. Pass in a byte array or a file path for the image. Pass in an album id if uploading to an existing album.
public string UploadPhoto(string album_id, string message, string filename, Byte[] bytes, string Token)
{
// Create Boundary
string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
// Create Path
string Path = #"https://graph.facebook.com/";
if (!String.IsNullOrEmpty(album_id))
{
Path += album_id + "/";
}
Path += "photos";
// Create HttpWebRequest
HttpWebRequest uploadRequest;
uploadRequest = (HttpWebRequest)HttpWebRequest.Create(Path);
uploadRequest.ServicePoint.Expect100Continue = false;
uploadRequest.Method = "POST";
uploadRequest.UserAgent = "Mozilla/4.0 (compatible; Windows NT)";
uploadRequest.ContentType = "multipart/form-data; boundary=" + boundary;
uploadRequest.KeepAlive = false;
// New String Builder
StringBuilder sb = new StringBuilder();
// Add Form Data
string formdataTemplate = "--{0}\r\nContent-Disposition: form-data; name=\"{1}\"\r\n\r\n{2}\r\n";
// Access Token
sb.AppendFormat(formdataTemplate, boundary, "access_token", HttpContext.Current.Server.UrlEncode(Token));
// Message
sb.AppendFormat(formdataTemplate, boundary, "message", message);
// Header
string headerTemplate = "--{0}\r\nContent-Disposition: form-data; name=\"{1}\"; filename=\"{2}\"\r\nContent-Type: {3}\r\n\r\n";
sb.AppendFormat(headerTemplate, boundary, "source", filename, #"application/octet-stream");
// File
string formString = sb.ToString();
byte[] formBytes = Encoding.UTF8.GetBytes(formString);
byte[] trailingBytes = Encoding.UTF8.GetBytes("\r\n--" + boundary + "--\r\n");
byte[] image;
if (bytes == null)
{
image = File.ReadAllBytes(HttpContext.Current.Server.MapPath(filename));
}
else
{
image = bytes;
}
// Memory Stream
MemoryStream imageMemoryStream = new MemoryStream();
imageMemoryStream.Write(image, 0, image.Length);
// Set Content Length
long imageLength = imageMemoryStream.Length;
long contentLength = formBytes.Length + imageLength + trailingBytes.Length;
uploadRequest.ContentLength = contentLength;
// Get Request Stream
uploadRequest.AllowWriteStreamBuffering = false;
Stream strm_out = uploadRequest.GetRequestStream();
// Write to Stream
strm_out.Write(formBytes, 0, formBytes.Length);
byte[] buffer = new Byte[checked((uint)Math.Min(4096, (int)imageLength))];
int bytesRead = 0;
int bytesTotal = 0;
imageMemoryStream.Seek(0, SeekOrigin.Begin);
while ((bytesRead = imageMemoryStream.Read(buffer, 0, buffer.Length)) != 0)
{
strm_out.Write(buffer, 0, bytesRead); bytesTotal += bytesRead;
}
strm_out.Write(trailingBytes, 0, trailingBytes.Length);
// Close Stream
strm_out.Close();
// Get Web Response
HttpWebResponse response = uploadRequest.GetResponse() as HttpWebResponse;
// Create Stream Reader
StreamReader reader = new StreamReader(response.GetResponseStream());
// Return
return reader.ReadToEnd();
}
You have to construct the multipart/form-data yourself using byte arrays.
Anyway I've already done this. You can check out the Facebook Graph Toolkit at http://computerbeacon.net/ . I'll update the toolkit to version 0.8 in a few days, which will include this "post photo to facebook wall" function as well as other new features and updates.
I was able to post pictures using RestSharp:
// url example: https://graph.facebook.com/you/photos?access_token=YOUR_TOKEN
request.AddFile("source", imageAsByteArray, openFileDialog1.SafeFileName, getMimeType(Path.GetExtension(openFileDialog1.FileName)));
request.addParameter("message", "your photos text here");
User API or Page API for posting photos
How to convert Image to Byte Array
Note: I was passing an empty string as the mime type and facebook was smart enough to figure it out.
Maybe useful
[TestMethod]
[DeploymentItem(#".\resources\velas_navidad.gif", #".\")]
public void Post_to_photos()
{
var ImagePath = "velas_navidad.gif";
Assert.IsTrue(File.Exists(ImagePath));
var client = new FacebookClient(AccessToken);
dynamic parameters = new ExpandoObject();
parameters.message = "Picture_Caption";
parameters.subject = "test 7979";
parameters.source = new FacebookMediaObject
{
ContentType = "image/gif",
FileName = Path.GetFileName(ImagePath)
}.SetValue(File.ReadAllBytes(ImagePath));
//// Post the image/picture to User wall
dynamic result = client.Post("me/photos", parameters);
//// Post the image/picture to the Page's Wall Photo album
//fb.Post("/368396933231381/", parameters); //368396933231381 is Album id for that page.
Thread.Sleep(15000);
client.Delete(result.id);
}
Reference:
Making Requests

Categories