在.NET中用picasa创建新专辑

时间:2011-09-08 00:09:09

标签: c# .net post webclient picasa

我正在尝试将相册发布到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();
}

2 个答案:

答案 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,并作为对象的一部分到期。您只需要访问令牌字符串进行授权。