我正在尝试将相册发布到picasa,但始终会收到“错误请求”的回复。 我应该使用HttpRequest类吗?
System.Net.WebClient wc = new System.Net.WebClient();
wc.Headers.Add("Authorization", "AuthSub token=\"" + token + "\"");
wc.Headers.Add("GData-Version", "2");
string data = "<entry xmlns='http://www.w3.org/2005/Atom' " +
"xmlns:media='http://search.yahoo.com/mrss/' " +
"xmlns:gphoto='http://schemas.google.com/photos/2007'>" +
"<title type='text'>" + name + "</title>" +
"<summary type='text'>" + descr + "</summary>" +
"<gphoto:location>asd</gphoto:location>" +
"<gphoto:access>" + access + "</gphoto:access>" +
"<gphoto:timestamp>1152255600000</gphoto:timestamp>" +
"<media:group>" +
"<media:keywords>adds</media:keywords>" +
"</media:group>" +
"<category scheme='http://schemas.google.com/g/2005#kind' " +
"term='http://schemas.google.com/photos/2007#album'></category>" +
"</entry>";
try
{
string response = wc.UploadString("https://picasaweb.google.com/data/feed/api/user/default", "post", data);
return response;
}
catch (Exception e)
{
return e.ToString();
}
答案 0 :(得分:4)
Google为picasa [.net]集成提供了便利的API:
http://code.google.com/apis/picasaweb/docs/1.0/developers_guide_dotnet.html
手工编写所有代码毫无意义!
这是一些代码(vb.net,但它很简单):
Public Shared Function CreateAlbum(ByVal albumTitle As String) As AlbumAccessor
Dim newAlbum As New AlbumEntry()
newAlbum.Title.Text = albumTitle
Dim ac As New AlbumAccessor(newAlbum)
ac.Access = "public"
Dim feedUri As New Uri(PicasaQuery.CreatePicasaUri(ConfigurationManager.AppSettings("GData_Email")))
Dim albumEntry As PicasaEntry = CreateAuthenticatedRequest().Insert(feedUri, newAlbum)
Return New AlbumAccessor(albumEntry)
End Function
Public Shared Function CreateAuthenticatedRequest() As PicasaService
Dim service As New PicasaService(ConfigurationManager.AppSettings("GData_AppName"))
service.setUserCredentials(ConfigurationManager.AppSettings("GData_Email"), ConfigurationManager.AppSettings("GData_Password"))
Return service
End Function
答案 1 :(得分:1)
我知道这个已经老了,所以你可能已经有了答案。我也知道谷歌确实制作了一个API但是.net它只适用于第一版Picasa而你正试图使用第二版,就像我一样。我遇到了你的帖子,并认为我会为你提供一个答案如果你还在尝试解决这个问题,或者其他人遇到这个帖子而想要答案。
我看到了一些可能导致您出现问题的事情。首先,您似乎将身份验证协议与版本混合和匹配。对于第二版Google Picasa API,我认为您需要使用OAuth2协议,而不是AuthSub协议。我没有尝试使用AuthSub。第二个问题是我不相信你的标题中有足够的信息(缺少内容长度,内容类型和主机[尽管你在使用webclient时可能不需要主机])。我发现的一种方法是确保我的请求运行良好(而且老实说是救命)是去Google上的OAuth2Playground:Oauth2Playground。在这里,您可以创建令牌和请求,并在成功请求时轻松查看其标题和发布信息。
以下是我编写的一段代码,可以创建相册。要创建,您必须拥有带有访问代码的经过身份验证的令牌(您可能希望首先获取用户权限并存储其刷新令牌,然后刷新以获取会话access_token)access_token将在标头的授权行中传递。它还解析响应并从响应和albumid中获取成功变量。响应时会返回相册的整个xml Feed,因此如果您愿意,可以直接阅读并直接使用它的详细信息)
public bool CreatePicasaAlbum(GoogleUtility.Picasa.AlbumEntry.entry a, IGoogleOauth2AccessToken token)
{
TcpClient client = new TcpClient(picasaweb.google.com, 443);
Stream netStream = client.GetStream();
SslStream sslStream = new SslStream(netStream);
sslStream.AuthenticateAsClient(picasaweb.google.com);
byte[] contentAsBytes = Encoding.ASCII.GetBytes(a.toXmlPostString());
string data = a.toXmlPostString();
StringBuilder msg = new StringBuilder();
msg.AppendLine("POST /data/feed/api/user/default HTTP/1.1");
msg.AppendLine("Host: picasaweb.google.com");
msg.AppendLine("Gdata-version: 2");
msg.AppendLine("Content-Length: " + data.Length);
msg.AppendLine("Content-Type: application/atom+xml");
msg.AppendLine(string.Format(GetUserInfoDataString(), token.access_token));
msg.AppendLine("");
byte[] headerAsBytes = Encoding.ASCII.GetBytes(msg.ToString());
sslStream.Write(headerAsBytes);
sslStream.Write(contentAsBytes);
StreamReader reader = new StreamReader(sslStream);
bool success = false;
string albumID = "";
while (reader.Peek() > 0)
{
string line = reader.ReadLine();
if (line.Contains("HTTP/1.1 201 Created")) { success = true; }
if (line.Contains("Location: https") && string.IsNullOrWhiteSpace(albumID))
{
var aiIndex = line.LastIndexOf("/");
albumID = line.Substring(aiIndex + 1);
}
System.Diagnostics.Debug.WriteLine(line);
if (line == null) break;
}
return success;
}
/// <summary>
/// User Info Data String for Authorization on TCP requests
/// [Authorization: OAuth {0}"]
/// </summary>
/// <returns></returns>
private string GetUserInfoDataString()
{
return "Authorization: OAuth {0}";
}
抱歉,我应该补充一点,我创建了一个对象,它返回上面的专辑条目xml的提要字符串。 feed xml与文档匹配。我将时间戳保留为空白,因为默认标记是在您创建它时,我还没弄清楚如果可以将任何内容放入类别中,那么我也将其留空。
<entry xmlns='http://www.w3.org/2005/Atom' xmlns:media='http://search.yahoo.com/mrss/' xmlns:gphoto='http://schemas.google.com/photos/2007'>
<title type='text'>Created from code</title>
<summary type='text'>Code created this album</summary>
<gphoto:location>somewhere</gphoto:location>
<gphoto:access>public</gphoto:access>
<gphoto:timestamp></gphoto:timestamp>
<media:group>
<media:keywords>test, album, fun</media:keywords>
</media:group>
<category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/photos/2007#album'>
</category>
</entry>
另一个编辑:IGoogleOauth2AccessToken是我创建的另一个用于容纳令牌详细信息的类。您真正需要传递的是刷新OAuth2令牌时获得的access_token字符串。我的令牌外壳代码只有access_code,token_type,并作为对象的一部分到期。您只需要访问令牌字符串进行授权。