使用Graph API将图像从.NET发布到Facebook墙

Tor*_*hde 5 .net c# facebook facebook-graph-api

我正在使用Facebook的Javascript API来开发一个需要能够将图像发布到用户墙的应用程序.据我所知,应用程序的那部分需要服务器端,因为它需要将图像数据发布为"multipart/form-data".

注意:这不是使用"post"的简单版本,而是真正的"照片"方法.

http://graph.facebook.com/me/photos

我认为我面临两个问题,一个.NET和一个Facebook问题:

Facebook问题:我不太确定是否所有参数都应作为multipart/form-data(包括access_token和message)发送.唯一的代码示例是使用cUrl util/application.

.NET问题:我从未发过.NET的 multipart/form-data请求,我不确定.NET是否自动创建mime-parts,或者我是否必须以某种特殊方式对参数进行编码.

这有点难以调试,因为我从Graph API得到的唯一错误响应是"400 - 错误请求".下面是我决定写这个问题时的代码(是的,它有点冗长:-)

最终的答案当然是从.NET发布图像的示例片段,但我可以满足于更少.

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

小智 4

以下是如何上传二进制数据的示例。但是上传到 /me/photos 不会将图像发布到墙上 :( 图像保存到应用程序的相册中。我不知道如何在提要中宣布它。另一种方法是将图像发布到“墙上”相册”,URL==“ graph.facebook.com/%wall-album-id%/photos ”。但没有找到任何方法来创建这样的相册(用户通过网站上传图像时创建它)。

{
    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;
}
Run Code Online (Sandbox Code Playgroud)