2011-02-04 129 views
5

我正在使用Facebook的Javascript API來開發將需要能夠將圖像發佈到用戶牆上的應用程序。 據我所知,應用程序的這部分需要在服務器端,因爲它需要將圖像數據發佈爲「multipart/form-data」。使用圖形API將圖像從.NET發佈到Facebook牆

注意:這不是使用「後」的簡單版本,而是真正的「照片」方法。

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

我想我面臨兩個問題,一個.NET和Facebook的問題:

Facebook的問題:我不太清楚,如果所有的參數應該被髮送的多/表單數據(包括access_token和消息)。唯一的代碼示例使用cUrl util /應用程序。

.NET問題:我從來沒有發出從.NET的multipart/form-data的請求,我不知道,如果.NET自動創建的MIME部分,或者如果我有編碼中的一些參數特殊的方式。

調試有點困難,因爲我從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(); 
    } 
} 

回答

4

以下是如何上傳二進制數據的示例。但是,上傳到/我/照片不會將圖像發佈到牆上:(將圖像保存到應用程序的相冊中,我一直在如何在提要中發佈它,但另一種方法是將圖像發佈到「Wall相冊「,通過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; 
} 
1

您必須使用字節數組自己構造multipart/form-data。 無論如何,我已經這樣做了。您可以在http://computerbeacon.net/查看Facebook Graph Toolkit。我會在幾天內將該工具包更新到0.8版本,其中包括「發佈到Facebook牆上的照片」功能以及其他新功能和更新。

+0

謝謝 - 期待它進行旋轉。 – 2011-02-06 19:34:09

+0

無法聯繫到此網站 – zchpit 2018-02-12 20:53:02

3

整理了使用@菲茨的代碼類方法。傳入的字節數組或該圖像的文件路徑。如果上傳到現有的相冊中的相冊ID傳遞。

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(); 
} 
1

我曾經是一個竹葉提取使用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 APIPage API張貼照片

How to convert Image to Byte Array

注:我是路過一個空字符串作爲MIME類型和Facebook很聰明,看着辦吧。

0

也許有用

 [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); 
     } 

參考: Making Requests

相關問題