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

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

Related

Unable to upload file to salesforce using c#

I am using salesforce v49.0. I wrote code to upload file(txt file) from my directory to salesforce.
I have created a folder in my salesforce account.
I am getting Bad Request while trying to upload.
Please help to find the solution or suggest any other ways to upload the file.
My Code
string oauthToken = (string)loginResponse["access_token"];
string serviceUrl = (string)loginResponse["instance_url"];
var doc = new sfdcDocument();
doc.Name = "DocumentbyDuke";
doc.FolderId = "05He0000RE00CcKDERTD";
doc.Type = "txt";
doc.Keywords = "123";
doc.Description = "123";
string boundary = "----" + DateTime.Now.Ticks.ToString("x");
var uri = serviceUrl + "/services/data/v49.0/sobjects/Document/";
var req = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(uri);
req.Headers.Add("Authorization: OAuth " + oauthToken);
req.ContentType = "multipart/form-data; boundary=" + boundary;
req.Method = "POST";
var os = req.GetRequestStream();
// Add header for JSON part
string body = "";
body += "\r\n--" + boundary + "\r\n"; ;
body += "Content-Disposition: form-data; name='entity_document'\r\n";
body += "Content-Type: application/json\r\n\r\n";
// Add document object data in JSON
body += JsonConvert.SerializeObject(doc);
// Add header for binary part
body += "\r\n--" + boundary + "\r\n"; ;
body += "Content-Disposition: form-data; name='Body'; filename='1.txt'\r\n";
body += "Content-Type: binary/octet-stream\r\n\r\n";
// Add header data to request
byte[] data = System.Text.Encoding.ASCII.GetBytes(body);
os.Write(data, 0, data.Length);
// Add file to reqeust
FileStream fileStream = new FileStream(#"C:\Users\AprilFile.txt", FileMode.Open, FileAccess.ReadWrite);
byte[] buffer = new byte[4096];
int bytesRead = 0;
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
{
os.Write(buffer, 0, bytesRead);
}
fileStream.Close();
// Add trailer
byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
os.Write(trailer, 0, trailer.Length);
os.Close();
// Do the post and get the response.
WebResponse resp;
try
{
resp = req.GetResponse();
}
catch (WebException ex)
{
resp = ex.Response;
}
//if (resp == null) return null;
var sr = new System.IO.StreamReader(resp.GetResponseStream());
08H, as shown in your comment is not the Key Prefix for any type of Folder. It appears to belong to an obscure sObject called CleanBatchErrorLog.
05H corresponds to ContentDistributionView, which is also incorrect.
While there may be other issues, you definitely need to locate the correct folder id to store this document.

Exe destroys itself

I have made an console app (exe) with C#. Application is used to send some http requests to server. It sends json to call server's API to execute some work. I save cookies in environmental variable.
We have noticed some weird behavior with this exe. With some sequence(we were not able to find out what sequence this is) of API calls ( api is called by command line arguments) the exe destroys itself. Its size becomes 0KB from starting 15MB. I have never seen that kind of behavior before. Do you have any idea what could it be?
This is the main part of code that creates http request, and other uploads file...
static public JObject UploadFile(string fileName)
{
HttpWebRequest requestToServer = (HttpWebRequest)WebRequest.Create(serverDomain + directory + "/File");
string boundaryString = "----SomeRandomText";
requestToServer.AllowWriteStreamBuffering = false;
requestToServer.Method = WebRequestMethods.Http.Post;
requestToServer.ContentType = "multipart/form-data; boundary=" + boundaryString;
requestToServer.KeepAlive = false;
if (Environment.GetEnvironmentVariable("dopinus.e2.session", EnvironmentVariableTarget.User) != null)
{
CookieContainer cookies = new CookieContainer();
cookies.Add(new Uri(serverDomain), new Cookie("dopinus.e2.session", Environment.GetEnvironmentVariable("dopinus.e2.session", EnvironmentVariableTarget.User).ToString()));
requestToServer.CookieContainer = cookies;
}
ASCIIEncoding ascii = new ASCIIEncoding();
string boundaryStringLine = "\r\n--" + boundaryString + "\r\n";
byte[] boundaryStringLineBytes = ascii.GetBytes(boundaryStringLine);
string lastBoundaryStringLine = "\r\n--" + boundaryString + "--\r\n";
byte[] lastBoundaryStringLineBytes = ascii.GetBytes(lastBoundaryStringLine);
string myFileDescriptionContentDisposition = String.Format(
"Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}",
"myFileDescription",
"A sample file description");
byte[] myFileDescriptionContentDispositionBytes = ascii.GetBytes(myFileDescriptionContentDisposition);
string fileUrl = fileName;
string myFileContentDisposition = String.Format(
"Content-Disposition: form-data;name=\"{0}\"; " + "filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n",
"myFile", Path.GetFileName(fileUrl), Path.GetExtension(fileUrl));
byte[] myFileContentDispositionBytes = ascii.GetBytes(myFileContentDisposition);
FileInfo fileInfo = new FileInfo(fileUrl);
long totalRequestBodySize = boundaryStringLineBytes.Length * 2 + lastBoundaryStringLineBytes.Length + myFileDescriptionContentDispositionBytes.Length + myFileContentDispositionBytes.Length + fileInfo.Length;
requestToServer.ContentLength = totalRequestBodySize;
using (Stream s = requestToServer.GetRequestStream())
{
s.Write(boundaryStringLineBytes, 0, boundaryStringLineBytes.Length);
s.Write(myFileDescriptionContentDispositionBytes, 0,
myFileDescriptionContentDisposition.Length);
s.Write(boundaryStringLineBytes, 0, boundaryStringLineBytes.Length);
s.Write(myFileContentDispositionBytes, 0,
myFileContentDispositionBytes.Length);
FileStream fileStream = new FileStream(fileUrl, FileMode.Open,
FileAccess.Read);
byte[] buffer = new byte[1024];
int bytesRead = 0;
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
{
s.Write(buffer, 0, bytesRead);
}
fileStream.Close();
s.Write(lastBoundaryStringLineBytes, 0, lastBoundaryStringLineBytes.Length);
}
WebResponse response = requestToServer.GetResponse();
StreamReader responseReader = new StreamReader(response.GetResponseStream());
string replyFromServer = responseReader.ReadToEnd();
JObject jsonResult = JObject.Parse(replyFromServer);
//CreateErrorLog(replyFromServer);
CreateResponse(replyFromServer);
return jsonResult;
}
static public JObject request(string json)
{
var httpWebRequest = (HttpWebRequest)WebRequest.Create(serverDomain + directory + "/json.rpc");
httpWebRequest.ContentType = "text/json";
httpWebRequest.Method = "POST";
httpWebRequest.CookieContainer = new CookieContainer();
if (Environment.GetEnvironmentVariable("dopinus.e2.session", EnvironmentVariableTarget.User) != null)
{
CookieContainer cookies = new CookieContainer();
cookies.Add(new Uri(serverDomain), new Cookie("dopinus.e2.session", Environment.GetEnvironmentVariable("dopinus.e2.session", EnvironmentVariableTarget.User).ToString()));
httpWebRequest.CookieContainer = cookies;
httpWebRequest.Headers.Add("dopinus.e2.session", Environment.GetEnvironmentVariable("dopinus.e2.session", EnvironmentVariableTarget.User).ToString());
}
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
streamWriter.Write(json);
streamWriter.Flush();
streamWriter.Close();
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
if (Environment.GetEnvironmentVariable("dopinus.e2.session", EnvironmentVariableTarget.User) == null)
{
foreach (Cookie cook in httpResponse.Cookies)
{
Environment.SetEnvironmentVariable(cook.Name, cook.Value, EnvironmentVariableTarget.User);
}
}
else if (Environment.GetEnvironmentVariable("dopinus.e2.session", EnvironmentVariableTarget.User) != null)
{
foreach (Cookie cook in httpResponse.Cookies)
{
if (cook.Name == "dopinus.e2.session" && cook.Value != Environment.GetEnvironmentVariable("dopinus.e2.session", EnvironmentVariableTarget.User))
{
Environment.SetEnvironmentVariable(cook.Name, cook.Value, EnvironmentVariableTarget.User);
}
}
}
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
JObject jsonResult = JObject.Parse(result);
//CreateErrorLog(result);
CreateResponse(result);
return jsonResult;
}
}
}

Http multipart request from windows phone 8 to send an text and an image using C# in WP8

I need make a multipart post request to a Rest service to send an image and a string but I can't do the code work. this is the code and I make a comment with capital letters where I get the exception and the exception message in the catch block.
public async Task<bool> addImages(Project project)
{
bool success = false;
string uuid = project.uuid;
if (uuid.Equals(""))
{
return success;
}
mUploadedImages = 0;
mProject = project;
string service = "service/imagen-project/add";
string serviceURL = mBaseURL + "/pwpcloud/" + service;
//build the REST request
// HTTP web request
string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
var httpWebRequest = (HttpWebRequest)WebRequest.Create(serviceURL);
httpWebRequest.ContentType = string.Format("multipart/form-data; boundary={0}", boundary);
httpWebRequest.Method = "POST";
httpWebRequest.AllowWriteStreamBuffering = false;
//Calculate the total size of the upload content.
string boundaryStringLine = "\r\n--" + boundary + "\r\n";
byte[] boundaryStringLineBytes = Encoding.UTF8.GetBytes(boundaryStringLine);
string lastBoundaryStringLine = "\r\n--" + boundary + "--\r\n";
byte[] lastBoundaryStringLineBytes = Encoding.UTF8.GetBytes(lastBoundaryStringLine);
// Get the byte array of the myFileDescription content disposition
string myFileDescriptionContentDisposition = String.Format(
"Content-Dis-data; name=\"{0}\"\r\n\r\n","project");
byte[] myFileDescriptionContentDispositionBytes = Encoding.UTF8.GetBytes(myFileDescriptionContentDisposition);
byte[] uuidBytes = Encoding.UTF8.GetBytes(project.uuid);
string fileUrl = "isostore:/" + project.Name + "_ID" + project.ID + "_Pictures/Pic_1.jpg";
string fileName = project.Name + "_ID" + project.ID + "_Pictures/Pic_1.jpg";
string myFileContentDisposition = String.Format("Content-Dis-data;name=\"{0}\"; " +
"filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n", "myFile", Path.GetFileName(fileUrl), "image/png");
byte[] myFileContentDispositionBytes = Encoding.UTF8.GetBytes(myFileContentDisposition);
IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication();
var fileStream = isoStore.OpenFile(fileName, FileMode.Open, FileAccess.Read);
byte[] imageBytes = new byte[fileStream.Length];
// Calculate the total size of the HTTP request
long totalRequestBodySize = boundaryStringLineBytes.Length * 2 + lastBoundaryStringLineBytes.Length + myFileDescriptionContentDispositionBytes.Length + uuidBytes.Length +
+myFileContentDispositionBytes.Length + imageBytes.Length;
httpWebRequest.ContentLength = totalRequestBodySize;
//Set cripted authorization -- WORKS FINE
setAuthorization(httpWebRequest, service, WEBSERVICE_REQUEST_TYPE_POST);
// Write the request Asynchronously
using (var stream = await Task.Factory.FromAsync<Stream>(httpWebRequest.BeginGetRequestStream, httpWebRequest.EndGetRequestStream, null))
{
// Send the file description content disposition over to the server
await stream.WriteAsync(boundaryStringLineBytes, 0, boundaryStringLineBytes.Length);
await stream.WriteAsync(myFileDescriptionContentDispositionBytes, 0, myFileDescriptionContentDisposition.Length);
await stream.WriteAsync(uuidBytes, 0, uuidBytes.Length);
// Send the file content disposition over to the server
await stream.WriteAsync(boundaryStringLineBytes, 0, boundaryStringLineBytes.Length);
await stream.WriteAsync(myFileContentDispositionBytes, 0, myFileContentDispositionBytes.Length);
fileStream.Read(imageBytes, 0, imageBytes.Length);
await stream.WriteAsync(imageBytes, 0, imageBytes.Length);
fileStream.Close();
// Send the last part of the HTTP request body
await stream.WriteAsync(lastBoundaryStringLineBytes, 0, lastBoundaryStringLineBytes.Length);
}
try
{
var responseTask = Task.Factory.FromAsync<WebResponse>(httpWebRequest.BeginGetResponse, httpWebRequest.EndGetResponse, null);
using (var response = (HttpWebResponse)await responseTask) //I GET THE EXCEPCION HERE (
{
string data;
// Read the response into a Stream object.
Stream responseStream = response.GetResponseStream();
using (var reader = new StreamReader(responseStream))
{
data = reader.ReadToEnd();
}
responseStream.Close();
}
}
catch (Exception e)
{
string err = e.Message; // err = "The remote server returned an error: NotFound" but the ServiceURL is ok
throw;
}
return success;
}
I could run this in a desktop program using C++ but I couldn't find any class to do it in C# using the same "sctructure". This is the C++ code:
void WebServicesClient::addImages(PW::Project *project){
QString uuid = project->getCloudUUID();
if (uuid.isEmpty()) /// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
return;
mUploadedImages = 0;
mProject = project;
QNetworkRequest request;
QString serviceURL = mBaseURL+"/service/imagen-project/add";
request.setUrl(QUrl(serviceURL));
// request.setHeader(QNetworkRequest::ContentTypeHeader, "multipart/form-data");
QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
QHttpPart textPart;
textPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"project\""));
textPart.setBody(uuid.toAscii());
QHttpPart imagePart;
imagePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/png"));
QString fileName = project->getImages().at(0)->getFileName();
QString header = "form-data; name=\"file\"";
header += "; filename=\"" + fileName + "\"";
imagePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant(header));
QFile *file = new QFile(project->getImages().at(0)->getFullPath());
file->open(QIODevice::ReadOnly);
imagePart.setBodyDevice(file);
file->setParent(multiPart); // we cannot delete the file now, so delete it with the multiPart
multiPart->append(textPart);
multiPart->append(imagePart);
setAuthorization(request, "service/imagen-project/add", WEBSERVICE_REQUEST_TYPE_POST);
QObject::connect(mNetwork, SIGNAL(finished(QNetworkReply *)),
this, SLOT(onAddImageFinished(QNetworkReply*)));
emit statusChanged(0, "Uploading " + project->getImages().at(0)->getFileName());
QNetworkReply *reply = mNetwork->post(request,multiPart);
}
I hope someone can help me.
Thanks everyone!

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

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?

problem in uploading data with HttpWebRequest

Request you to please help me to solve my problem. I am new to web-services and HTTP.
I wrote following code to update data to website. Code run; but I am not able to see my data if uploaded. Here we have facility to see what data is getting uploaded but I am not able to see my data.
// Above URL is not real as I do not want to disclose real URL as of Now
Uri targetUrl = new Uri("http://www.x86map.com/post-embed/ewspost");
HttpWebRequest request = null;
StringBuilder sb = new StringBuilder();
Stream requestStream = null;
try
{
request = (HttpWebRequest)WebRequest.Create(targetUrl);
using (StreamReader inputReader = new StreamReader("C:\\SupportXml.xml"))
{
sb.Append(inputReader.ReadToEnd());
}
String postData = sb.ToString();
byte[] postDataBytes = Encoding.UTF8.GetBytes(postData);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = postDataBytes.Length;
request.KeepAlive = true;
request.Accept = "*/*";
request.Headers.Add("Cache-Control", "no-cache");
request.Headers.Add("Accept-Language", "en-us");
request.Headers.Add("Accept-Encoding", "gzip,deflate");
request.Headers.Add("Accept-Charset", "ISO-8859-1,utf-8,q=0.66,*;q=0.66");
requestStream = request.GetRequestStream();
requestStream.Write(postDataBytes, 0, postDataBytes.Length);
}
catch (Exception ex)
{
Console.Write(ex.ToString());
}
finally
{
if (null != requestStream)
requestStream.Close();
}
URL I mentioned in Code is not real. Please let me know what is the problem in my code.
Following is the Java code working perfect. I want to convert same code in C#.
// Above URL is not real as I do not want to disclose real URL as of Now
String urlString = "http://www.x86map.com/post-embed/ewspost";
StringBuffer s = new StringBuffer();
try
{
String line = null;
BufferedReader input = new BufferedReader(new FileReader("C:\\SupportXml.xml"));
while ((line = input.readLine()) != null)
{
s.append(line);
s.append(System.getProperty("line.separator"));
}
String xmlDataString = s.toString();
int length = xmlDataString.length();
System.out.println("length " + length);
URL url = new URL(urlString);
System.out.println(url.toString());
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("POST");
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setAllowUserInteraction(false);
connection.setUseCaches(false);
connection.setRequestProperty("Accept", "*/*");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
connection.setRequestProperty("Content-Length", (String.valueOf(length)));
connection.setRequestProperty("Cache-Control", "no-cache");
connection.setRequestProperty("Accept-Language", "en-us");
connection.setRequestProperty("Accept-Encoding", "gzip,deflate");
connection.setRequestProperty("Connection", "Keep-Alive");
connection.setRequestProperty("Accept-Charset", "ISO-8859-1,utf-8,q=0.66, *;q=0.66");
BufferedOutputStream bos = new BufferedOutputStream(connection.getOutputStream());
BufferedReader reader = new BufferedReader(new StringReader(xmlDataString));
System.out.println("Proxy Used :" + connection.usingProxy());
int dataRead;
bos.write("XML_string=".getBytes());
while ((dataRead = reader.read()) != -1)
{
bos.write(dataRead);
}
bos.flush();
bos.close();
BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String res = null;
while ((res = br.readLine()) != null)
{
}
br.close();
}
catch (IOException e)
{
e.printStackTrace();
}
Please help me to resolve this issue.
Thanks and Regards,
map125
You may find it helps to include
requestStream.Flush();
before .Closeing it.
Stream.Flush
I do not see the code that actually gets the response. Is this want is missing?
using (var r = new StreamReader(request.GetResponse().GetResponseStream(), Encoding.UTF8))
result = r.ReadToEnd();

Categories