本文介绍了访问直通OAuth的imgUr(上传到用户帐户)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

要开始做这个简单的任务,我研究过了,我已经作为示例的跟随和复制的步骤,程序可以上传图片匿名:

 私人只读客户端Id为String =我的客户ID'=> ...............
私人只读ClientSecret的String =我的客户秘密'=> ........................................

' 用法:
昏暗的URL的String = UploadImage(C:\ image.jpg文件)中:MessageBox.Show(URL)
公共职能UploadImage(BYVAL图像作为字符串)

    昏暗W¯¯作为新的Web客户端()
    w.Headers.Add(授权,客户ID&放大器;客户端Id)
    昏暗的按键作为新System.Collections.Specialized.NameValueCollection

    尝试

        Keys.Add(形象,Convert.ToBase64String(File.ReadAllBytes(图片)))
        昏暗responseArray为字节()= w.UploadValues​​(https://api.imgur.com/3/image键)
        昏暗的结果= Encoding.ASCII.GetString(responseArray)
        昏暗的章作为新System.Text.RegularEx pressions.Regex(链接:。(*)?,)
        昏暗的比赛由于比赛= reg.Match(结果)
        昏暗的URL的String = match.ToString.Replace(链接,).Replace(,).Replace(\ /,/)
        返回URL

    抓住参考译文异常

        的MessageBox.show(出事了。&放大器; s.Message)
        返回失败!

    结束尝试

端功能
 

但我真正希望做的是上传图片到我的用户帐户,该帐户是的http:// elektrostudios .imgur.com

我发现this问题,但什么他回答说不清楚了我(因为我的新手知识),反正我试图使用上述功能,但只发送 BEARER 头我的 ClientSecret ID'的原因如果我理解好什么 OAuth的2 API文档表示令牌也有可能是 ClientSecret 标识?,但我没有得到预期的结果。

所以,搜索的方式来获得适当的存取权限令牌我见过这让我发现 RestSharp 库,并知道如何发送请求别人的问题,我做了一些修改,用它搭配Imgur API,但我得到这个错误响应:

  {数据:{错误:CLIENT_ID和RESPONSE_TYPE是必需的,请求:\ / oauth2 \ /授权,法:POST },成功:假的,身份:400}
 

这是我有:

 公用Sub GetAccessToken()

    昏暗的XRC作为RestClient =新RestClient
    昏暗的grant_type的String =authorization_ code
    昏暗的要求作为新RestRequest(Method.POST)
    昏暗strBody作为字符串
    昏暗的响应,RestResponse
    昏暗strResponse作为字符串

    request.Method = Method.POST
    request.RequestFormat = DataFormat.Xml

    基本URL
    xrc.BaseUrl =htt​​ps://api.imgur.com

    资源
    request.Resource =oauth2 /授权

    格式的身体
    strBody =的String.Format(CLIENT_ID = {0}&放大器; RESPONSE_TYPE = {1},客户端ID,ClientSecret)

    添加身体的要求
    request.AddBody(授权,strBody)

    '执行
    响应= xrc.Execute(要求)

    解析响应
    strResponse = response.Content

    的MessageBox.show(response.Content.ToString)

结束小组
 

所以我的问题是2合1:

PS:请记住,即使获得访问令牌,我不知道如何使用它后,将其存储

我试图使用@ Plutonix 解决方案,但是当我尝试要求它抛出一个异常的令牌需要一个有效的PIN第一 我使用的是有效的客户端Id和ClientSecret,我想的东西更多?这里是code:

 私人imgUR作为新imgurAPI(我的客户ID,我的客户的秘密)

私人小组的button1_Click()处理Button1.Click

    昏暗的世行作为新的web浏览器
    imgUR.RequestPinBrowser(WB)

    下面的介绍抛出一个异常:
    需要一个有效的PIN第一
    昏暗的结果作为imgurAPI.imgUrResults = imgUR.RequestToken
    wb.Dispose()

    检查结果
    如果结果= imgurAPI.imgUrResults.OK然后

        假设该文件存在
        imgUR.UploadImage(C:\ test.jpg放在假)

        Clipboard.SetText(imgUR.LastImageLink)
        的MessageBox.show(imgUR.LastImageLink)

    其他
        的MessageBox.show(的String.Format(错误获得访问令牌状态:{0},
            result.ToString))
    结束如果

结束小组
 

解决方案

这是漫长的,因为它是多了还是少了compleat API:

公共类imgurAPI    这个API的imgUR组合和服务器响应    公共枚举imgUrResults        OK = 200'AKA Status200        错误我们返回        OtherAPIError = -1到目前为止,只是缺少ImgLink        InvalidToken = -2        InvalidPIN = -3'销过期        InvalidRequest = -4        TokenParseError = -5        结果,我们从服务器获取        BadRequestFormat = 400'Status400        AuthorizationError = 401'Status401        故宫= 403'Status403        NOTFOUND = 404'Status404坏网址端点        RateLimitError = 429'Status429RateLimit错误        SERVERERROR = 500'Status500内部服务器错误        UknownStatus = 700'我们还没有占它(还),                                        可能是微不足道的或新    结束枚举    容器很酷的东西,他们给我们    朋友兵种标志        公共属性AcctUserName作为字符串        公共属性AccessToken作为字符串        公共属性RefreshToken作为字符串        公共属性届满日期时间        公共子新()            AcctUserName =            AccessToken =            RefreshToken =            到期= DateTime.MinValue        结束小组        好友功能IsExpired()作为布尔            如果(到期> DateTime.Now)然后                返回False            其他                如果到期重置一切,让一些白痴犯规                揭露AccessToken和测试                AcctUserName =                AccessToken =                RefreshToken =                到期= DateTime.MinValue                返回TRUE            结束如果        端功能    末级    没有简单的男星!    与客户端ID和SecretID构造函数初始化    公共子新(CLID作为字符串,秘密作为字符串)        clientID的= CLID        clientSecret =秘密        myPin =        imgToken =新令牌        LastImageLink =        UseClipboard = TRUE        AnonOnly = FALSE    结束小组    与客户端ID和SecretID构造函数初始化    公共子新(CLID作为字符串)        clientID的= CLID        clientSecret =        myPin =        imgToken =新令牌        LastImageLink =        UseClipboard = TRUE        AnonOnly = TRUE    结束小组    私人clientID的作为字符串    私人clientSecret作为字符串    私人AnonOnly由于布尔= TRUE    令牌不公开    私人imgToken令牌    公共属性LastImageLink作为字符串    公共属性UseClipboard由于布尔    'precise时刻到期时为code使用    公共只读属性TokenExpiry为DATETIME        得到            如果imgToken状态并没有任何然后                返回imgToken.Expiry            其他                返回任何结果            结束如果        最终获取    高端物业    公共功能GetExpiryCountdown()作为字符串        返回的String.Format({0:HH \:毫米\:SS},GetExpiryTimeRemaining)    端功能    剩下的时间作为时间跨度    公共功能GetExpiryTimeRemaining()由于时间跨度        昏暗的TS作为新的时间跨度(0)        如果imgToken是没有那么            返回TS        结束如果        如果DateTime.Now> imgToken.Expiry然后            返回TS        其他            TS = imgToken.Expiry - DateTime.Now            返回TS        结束如果    端功能    公共功能IsTokenValid()作为布尔        如果imgToken是没有那么            返回False        结束如果        如果String.IsNullOrEmpty(imgToken.AcctUserName)然后            返回False        结束如果        如果imgToken.IsExpired然后            返回False        结束如果        返回TRUE    端功能    目前,该密码是从调用应用程序设置。也许有可能    饲料在日志中imgUr得到一个PIN    私人myPin作为字符串    公众只写属性脚作为字符串        设置(值作为字符串)            myPin =价值        结束设定    高端物业    导航到网页。    看到wb_DocumentCompleted为code到    从文档解析PIN    公用Sub RequestPinBrowser(BrowserCtl作为web浏览器)        如果AnonOnly然后            你不需要输入PIN佚名            抛出新ApplicationException的(A PIN是不是需要ANON上传)            退出小组        结束如果        如果BrowserCtl是没有那么            抛出新的ArgumentException(缺少有效的web浏览器参考)            退出小组        结束如果        imgur API格式         https://api.imgur.com/oauth2/authorize?client_id=YOUR_CLIENT_ID&response_type=REQUESTED_RESPONSE_TYPE&state=APPLICATION_STATE        昏暗的OAuthUrlTemplate =htt​​ps://api.imgur.com/oauth2/authorize?client_id={0}&response_type={1}&state={2}        昏暗ReqURL作为字符串=的String.Format(OAuthUrlTemplate,客户端ID,针,齐格)        BrowserCtl.Url =新的URI(ReqURL)    结束小组    公共功能GetAccessToken()作为imgUrResults        有不同类型的令牌请求        这只能通过提交的数据变化        昏暗的SREQ的String =的String.Format(CLIENT_ID = {0}&放大器; client_secret = {1}&安培; grant_type =引脚和放大器;针= {2},                                            客户端ID,clientSecret,myPin)        如果myPin =的String.Empty然后            返回imgUrResults.InvalidPIN        结束如果        如果AnonOnly然后返回imgUrResults.InvalidRequest        呼叫通用令牌处理器        返回RequestToken(SREQ)    端功能    请求令牌    专用功能RequestToken(sRequest作为字符串)作为imgUrResults        昏暗的URL的String =htt​​ps://api.imgur.com/oauth2/token/        昏暗myResult中作为imgUrResults = imgUrResults.OK        使用POST方法创建请求的URL,        昏暗的要求作为的WebRequest = WebRequest.Create(URL)        request.Method =POST        转换的要求,设置内容格式,长度        昏暗的数据字节()= System.Text.Encoding.UTF8.GetBytes(sRequest)        request.ContentType =应用/的X WWW的形式urlen codeD        request.ContentLength = data.Length        写上日期,请求流        昏暗DSTREAM作为物流= request.GetRequestStream        dstream.Write(数据,0,data.Length)        dstream.Close()        '上使用的反应和潜在WebException JSON        昏暗的JSON作为新JavaScriptSerializer()        'prepare一个响应        昏暗的响应,WebResponse类=无        昏暗SvrResponses作为词典(字符串,对象)        尝试            响应= request.GetResponse            转换状态code到纲领性结果            myResult中= GetResultFromStatus(CTYPE(响应,HttpWebResponse).STATUS code)        抓住EX作为WebException            一个坏/使用引脚将抛出一个异常            昏暗的RESP的String =新的StreamReader(ex.Response.GetResponseStream())。ReadToEnd()            SvrResponses = CTYPE(json.DeserializeObject(resp.ToString)                                    词典(字符串,对象))            myResult中= GetResultFromStatus(Convert.ToString(SvrResponses(状态)))        结束尝试        Console.WriteLine(CTYPE(响应,HttpWebResponse).StatusDescription)        Console.WriteLine(CTYPE(响应,HttpWebResponse).STATUS code)        'premature疏散        如果myResult中<> imgUrResults.OK然后            如果DSTREAM状态并没有任何然后                dstream.Close()                dstream.Dispose()            结束如果            如果响应状态并没有任何然后                response.Close()            结束如果            返回myResult中        结束如果        读响应流        DSTREAM = response.GetResponseStream        昏暗SvrResponseStr作为字符串        使用SR作为StreamReader的=新的StreamReader(DSTREAM)            流串            SvrResponseStr = sr.ReadToEnd            Console.WriteLine(SvrResponse)        结束使用        靠近流        dstream.Close()        dstream.Dispose()        response.Close()        尝试            使用JSON serialier来解析结果(S)            转换SvrRsponse到词典            SvrResponses = CTYPE(json.DeserializeObject(SvrResponseStr)                                    词典(字符串,对象))            从字典'得到的东西            imgToken.AccessToken = Convert.ToString(SvrResponses(access_token))            imgToken.RefreshToken = Convert.ToString(SvrResponses(refresh_token))            imgToken.AcctUserName = Convert.ToString(SvrResponses(account_username))            转换expires_in到某个时间点            昏暗nExp作为整数= Convert.ToInt32(Convert.ToString(SvrResponses(expires_in)))            imgToken.Expiry = Date.Now.Add(新时间跨度(0,0,nExp))            针是一次性使用            把它扔掉,因为它不再有效            myPin =        抓住EX为例外            的MessageBox.show(ex.Message)            myResult中= imgUrResults.TokenParseError        结束尝试        返回myResult中    端功能    公共接口尝试上传前检查PARAMS    公共功能UploadImage(文件名作为字符串,可选佚名由于布尔= FALSE)作为imgUrResults        如果AnonOnly然后            返回DoImageUpLoad(文件名,AnonOnly)        其他            如果IsTokenValid()= false,那么                返回imgUrResults.InvalidToken            结束如果        结束如果        应该是调用的应用程序来测试FileExist的工作        返回DoImageUpLoad(文件名,佚名)    端功能    实际的文件上传    专用功能DoImageUpLoad(文件名作为字符串,可选佚名由于布尔= FALSE)作为imgUrResults        昏暗的结果作为imgUrResults = imgUrResults.OK        LastImageLink =        尝试            创建一个Web客户端            使用wc =新Net.WebClient()                读图像                昏暗的值=新的NameValueCollection()从                        {                            {形象,Convert.ToBase64String(File.ReadAllBytes(文件名))}                        }                报头的类型取决于这是否是一个匿名或帐户上传                如果匿名然后                    wc.Headers.Add(授权,客户ID+ clientID的)                其他                    wc.Headers.Add(授权,承载及放大器; imgToken.AccessToken)                结束如果                '上传,得到响应                昏暗的响应= wc.UploadValues​​(https://api.imgur.com/3/upload.xml,值)                读响应转换成字节数组流                使用SR作为新的StreamReader(新的MemoryStream(响应))                    昏暗uplStatus作为字符串                    昏暗SvrResponse作为字符串= sr.ReadToEnd                    XDOC暗淡作为的XDocument = XDocument.Parse(SvrResponse)                    获得请求的状态                    uplStatus = xdoc.Root.Attribute(状态)。值                    结果= GetResultFromStatus(uplStatus)                    如果结果= imgUrResults.OK然后                        LastImageLink = xdoc.Descendants(链接)。值                        只覆盖服务器结果状态                        如果String.IsNullOrEmpty(LastImageLink)然后                            避免NRE别处                            LastImageLink =                            我们做错了什么事解析结果                            但是这一次是一种轻微                            结果= imgUrResults.OtherAPIError                        结束如果                    结束如果                结束使用                如果UseClipboard AndAlso(结果= imgUrResults.OK)然后                    Clipboard.SetText(LastImageLink)                结束如果            结束使用        抓住EX为例外            昏暗ERRMSG作为字符串= ex.Message            限速            如果ex.Message.Contains(429)然后                结果= imgUrResults.RateLimitError                ' 内部错误            elseif的ex.Message.Contains(500)然后                结果= imgUrResults.ServerError            结束如果        结束尝试        返回结果    端功能    专用功能GetResultFromStatus(状态作为字符串)作为imgUrResults        选择案例status.Trim            案200                返回imgUrResults.OK            案400                返回imgUrResults.BadRequestFormat            案401                返回imgUrResults.AuthorizationError            案403                返回imgUrResults.Forbidden            案404                返回imgUrResults.NotFound            案429                返回imgUrResults.RateLimitError            案500                返回imgUrResults.ServerError            案例否则                不要 - 制定出其他收益                返回imgUrResults.UknownStatus        最终选择    端功能    专用功能GetResultFromStatus(地位的Int32)作为imgUrResults        有些地方,我们得到一个字符串,其他整数        返回GetResultFromStatus(status.ToString)    端功能末级

如何使用它

该过程需要一个网络浏览器的用户导航并请求PIN码。为了测试/开发,我用了一个WebBrowser控件和陷入僵局从返回页面中的PIN码。

注:用于测试,我的imgUR帐户被设置为桌面,因为我们正在从一个桌面应用程序发送。此外,这是给你的图像发送到您的帐户。没有办法给别人上传到你的账户没有给你的秘密ID和/或嵌入你的主人ImgUR登录名和密码的应用程序。这是怎么ImgUR设计了它。

一个。创建imgUR对象:

 朋友imgUR作为imgurAPI
imgUR =新imgurAPI(小于你的客户端ID>,<您的秘密code基)
 

乙。得到一个针 - 方法一

 通过应用程序的WebBrowser控件
imgUR.RequestPinBrowser(WB)
 

这将带你到一个imgur页面,您必须授权密码的问题上传到您的帐户。输入您的账户名,密码,点击允许。与PIN一个新的页面会显示出来。从网页复制的PIN码进行一些其他的控制,可以把它交给了imgurAPI类。

有低于code解析密码页面,并把它变成另一种控制。

方法二

  • 使用自己的外部浏览器转到

https://api.imgur.com/oauth2/authorize? CLIENT_ID = YOUR_CLIENT_ID和放大器; RESPONSE_TYPE =引脚和放大器;状态=齐格

  • 登录
  • 复制您会收到成文本框什么的PIN将其发送到imgurAPI:
  • 设置PIN: imgUR.Pin =<< PIN码接收的GT;>

这个过程是相同的无论哪种方式,你是否想拥有包括在您的形式WebBrowser控件只是一个问题。 PIN码是唯一的好很短的时间,所以你必须使用它来获得访问令牌的时候了。

℃。获得访问令牌

 'imgUrResults是由类暴露枚举
昏暗的结果作为imgurAPI.imgUrResults = imgUR.RequestToken
 

注:

  • 的imgUR类将保持该标记
  • 在当前令牌在1小时内到期(3600秒)

D:上传文件
上传使用 imgUR.UploadImage(文件名,boolAnon)

文件名 - 文件上传

boolAnon - 布尔标志。假=上传此文件到您的帐户相较于匿名通用池方法。

例如:

 '获得令牌
昏暗的结果作为imgurAPI.imgUrResults = imgUR.RequestToken

检查结果
如果结果= imgurAPI.imgUrResults.OK然后
    假设该文件存在
    imgUR.UploadImage(C:\ TEMP \ London.jpg,FALSE)
其他
    的MessageBox.show(的String.Format(错误获得访问令牌状态:{0},
        result.ToString))
结束如果
 

的文件上传后,程序查找在响应中的链接。如果链接可以分析,这将是可从 LastImageLink 属性并粘贴到剪贴板为好。

其它属性,设置和方法

LastImageLink (字符串) - 上传的最后一幅图像的URL

UseClipBoard (布尔) - 如果为true,imgurAPI类职位上传的图片的链接到剪贴板

TokenExpiry (日期) - 即当前令牌到期日期时间

GetTokenTimeRemaining ()由于时间跨度 - 一个时间跨度再presenting多久当前令牌到期前

公共功能GetTokenCountdown()作为String - 格式化TimeRemaining串

公开只写属性脚作为String - 要获得访问令牌需要的PIN

公共功能IsTokenValid()作为布尔 - 当前令牌有效

公共功能IsTokenExpired ()作为布尔 - TimeRemaining简单的布尔版VS DateTime.Now

备注

  • 在令牌可续签或延长。但由于他们持续了一个小时,这似乎很多。
  • 引脚只有良好的时间很短。一旦密码被交换信物的imgurAPI(本级)清除PIN。如果有问题,得到令牌,你必须首先获得一个新的PIN(或粘贴最后一个,如果你只是得到它几分钟前)。
  • 上传的图片是不可见的世界的,除非/直到你改变你的帐户设置。
  • 您可以重置SecretID(设置 - >应用程序)。如果你这样做,你还需要重置它使用这个API类的应用程序,并重新编译(或从一个配置文件中读取)。

如果您使用的是 web浏览器控制得到一个密码,你可以添加这个code到 DocumentCompleted 事件刮从HTML的PIN:

 的WB是控制
昏暗HTMLDOC作为System.Windows.Forms.HtmlDocument = wb.Document
昏暗ELP作为System.Windows.Forms.HtmlElement = htmlDoc.GetElementById(针)

如果ELP状态并没有任何然后
    SPIN = elP.GetAttribute(价值)
    如果String.IsNullOrEmpty(SPIN)= false,那么
       用户必须按下按钮`imgUR.Pin = tbPIN.Text`
       '这样的情况下是在HTML变化时,用户可以覆盖
       并输入正确的PIN
       Me.tbPIN.Text = SPIN
    结束如果

结束如果
 


关于OAuth的型号

这是非官方的 - 从阅读的文档,并与API的信息了解到。适用于imgur API V3因为这个日期。

什么自动得到一个PIN。这种或那种方式,你必须导航到一个URL在浏览器中,输入您的帐户名和密码来获得一个PIN。这是设计让你自己,个人的授权一些外部应用程序来访问您的帐户的内容。

方法一上面使用.NET WebBrowser控件来做到这一点。通过这种方法,我们可以肯定的是你和imgur类两者都使用相同的端点/ URL,因为它通过浏览器控件发送你。

方法二只是你在某些浏览器去那里,任何浏览器。登录,获取密码,并将其粘贴到imgurAPI类。

无论方法,正确的端点/ URL中使用的是:

<一个href="https://api.imgur.com/oauth2/authorize?client_id=YOUR_CLIENT_ID&response_type=pin&state=foobar" rel="nofollow">https://api.imgur.com/oauth2/authorize?client_id=YOUR_CLIENT_ID&response_type=pin&state=foobar

使用使用imgurAPI类的窗体上的浏览器,我们显然我们可以肯定的是,你和类两者都使用相同的URL和客户端ID。在$ C $下的DocumentComplete 获取PIN码到文本框的您还需要设置它的类:

  myimgUR.PIN = tbPin code.Text
 

引脚是一次性使用的,而过期。

所以开发尤其是当你停止code,加一些东西然后重新运行自然,code将不再有旧令牌或PIN。如果最后一个PIN码是最近和的没有的提交,你可能没有得到一个新的,但我发现这是很难记住,如果是这样的话。

类把引脚作为一次性使用。一旦令牌已收到,它清除出去,因为他们一直在使用,不再有效的变量。


最后修改

  • 添加了一个匿名只有模式

要使用类上传仅在匿名模式(一般的网站,而不是您的帐户),该SecretID是不需要的。为此,使用新的构造函数重载:

 的Public Sub New(clientID的作为字符串)
 

该设置为只工作一个匿名类和一定的方法将返回错误或使用基于账户的方法,如为gettoken 当阵痛异常。如果你只是客户端ID初始化它,它仍然在 AnonOnly 模式之前,必须重新与该客户端ID和SecretID两者的对象。

有没有真正的理由使用它作为AnonOnly(除非你没有一个帐户),因为UploadImage方法允许你通过文件来指定它作为一个匿名上传:

 功能UploadImage(文件名作为字符串,
                     可选的匿名由于布尔= FALSE)作为imgUrResults
 

  • 在修订/澄清了imgUrResults枚举

这就是要包罗万象:一些回报指示由类检测到问题,其他都是这只是传承下去服务器响应

  • 删除 IsTokenExpired

IsTokenValid 更彻底。还有其他的方法来获取剩余时间或实际到期。

  • 新增各类错误捕获/处理
    • 要求输入PIN时,检查是否有有效的WebBrowser控件
    • 精制用于获取服务器状态code中的方法将图像上传后
    • 重新编排了一些处理给了优先收益类远程服务器的状态

To start doing this "simple" task I've researched for a procedure that I've taken as an example here to follow and reproduce the steps, the procedure can upload an image "anonymously":

Private ReadOnly ClientId As String = "My Client ID" ' => "..............."
Private ReadOnly ClientSecret As String = "My Client Secret" ' => "........................................"

' Usage:
' Dim url As String = UploadImage("C:\Image.jpg") : MessageBox.Show(url)
Public Function UploadImage(ByVal image As String)

    Dim w As New WebClient()
    w.Headers.Add("Authorization", "Client-ID " & ClientId)
    Dim Keys As New System.Collections.Specialized.NameValueCollection

    Try

        Keys.Add("image", Convert.ToBase64String(File.ReadAllBytes(image)))
        Dim responseArray As Byte() = w.UploadValues("https://api.imgur.com/3/image", Keys)
        Dim result = Encoding.ASCII.GetString(responseArray)
        Dim reg As New System.Text.RegularExpressions.Regex("link"":""(.*?)""")
        Dim match As Match = reg.Match(result)
        Dim url As String = match.ToString.Replace("link"":""", "").Replace("""", "").Replace("\/", "/")
        Return url

    Catch s As Exception

        MessageBox.Show("Something went wrong. " & s.Message)
        Return "Failed!"

    End Try

End Function

But what I really would like to do is upload the image into my user account, which is http://elektrostudios.imgur.com.

I've found this question but what him said in the answer is not clear for my (due to my newbie knowledges), anyways I've tried to use the function above but just sending the BEARER header with my ClientSecret ID 'cause If I understood good what the oauth 2 api documentation says the token could also be the ClientSecret Id?, but I don't get the expected result.

So searching the way to get a proper acces token I've seen this else question which helped me to discover RestSharp library and to know how to send the request, I did some modifications to use it with Imgur API but I'm getting this error-response:

{"data":{"error":"client_id and response_type are required","request":"\/oauth2\/authorize","method":"POST"},"success":false,"status":400}

This is what I have:

Public Sub GetAccessToken()

    Dim xrc As RestClient = New RestClient
    Dim grant_type As String = "authorization_code"
    Dim request As New RestRequest(Method.POST)
    Dim strBody As String
    Dim response As RestResponse
    Dim strResponse As String

    request.Method = Method.POST
    request.RequestFormat = DataFormat.Xml

    'Base URL
    xrc.BaseUrl = "https://api.imgur.com"

    'Resource
    request.Resource = "oauth2/authorize"

    'Format body
    strBody = String.Format("client_id={0}&response_type={1}", ClientId, ClientSecret)

    'Add body to request
    request.AddBody("Authorization", strBody)

    'Execute
    response = xrc.Execute(request)

    'Parse Response
    strResponse = response.Content

    MessageBox.Show(response.Content.ToString)

End Sub

So my question are 2 in 1:

PS: Please remember that even getting the access token I don't know how to use it after stored it.

I'm trying to use @Plutonix solution but when I try to request the Token it throws an exception "Need a valid PIN first", I'm using a valid ClientId and ClientSecret, I'm missing something more?, here is the code:

Private imgUR As New imgurAPI("my client id", "my client secret")

Private Sub Button1_Click() Handles Button1.Click

    Dim wb As New WebBrowser
    imgUR.RequestPinBrowser(wb)

    ' The instruction below throws an exception:
    ' "Need a valid PIN first"
    Dim result As imgurAPI.imgUrResults = imgUR.RequestToken
    wb.Dispose()

    ' check result
    If result = imgurAPI.imgUrResults.OK Then

        ' assumes the file exists
        imgUR.UploadImage("C:\Test.jpg", False)

        Clipboard.SetText(imgUR.LastImageLink)
        MessageBox.Show(imgUR.LastImageLink)

    Else
        MessageBox.Show(String.Format("Error getting access token. Status:{0}",
            result.ToString))
    End If

End Sub
解决方案

This is long, because it is more or less a compleat API:

Public Class imgurAPI
    ' combination of this API and imgUR server responses
    Public Enum imgUrResults
        OK = 200                        ' AKA Status200 

        ' errors WE return
        OtherAPIError = -1              ' so far, just missing ImgLink
        InvalidToken = -2
        InvalidPIN = -3                 ' pins expire
        InvalidRequest = -4
        TokenParseError = -5

        ' results we get from server
        BadRequestFormat = 400          ' Status400   
        AuthorizationError = 401        ' Status401  

        Forbidden = 403                 ' Status403   
        NotFound = 404                  ' Status404   ' bad URL Endpoint
        RateLimitError = 429            ' Status429   ' RateLimit Error
        ServerError = 500               ' Status500   ' internal server error

        UknownStatus = 700              ' We havent accounted for it (yet), 
                                        '   may be trivial or new
    End Enum

    ' container for the cool stuff they send us
    Friend Class Token
        Public Property AcctUserName As String
        Public Property AccessToken As String
        Public Property RefreshToken As String
        Public Property Expiry As DateTime

        Public Sub New()
            AcctUserName = ""
            AccessToken = ""
            RefreshToken = ""
            Expiry = DateTime.MinValue
        End Sub

        Friend Function IsExpired() As Boolean

            If (Expiry > DateTime.Now) Then
                Return False
            Else
                ' if expired reset everything so some moron doesnt
                ' expose AccessToken and test for ""
                AcctUserName = ""
                AccessToken = ""
                RefreshToken = ""
                Expiry = DateTime.MinValue
                Return True
            End If
        End Function

    End Class

    ' NO simple ctor!!!
    ' constructor initialized with ClientID and SecretID
    Public Sub New(clID As String, secret As String)
        clientID = clID
        clientSecret = secret
        myPin = ""
        imgToken = New Token
        LastImageLink = ""
        UseClipboard = True
        AnonOnly = False
    End Sub

    ' constructor initialized with ClientID and SecretID
    Public Sub New(clID As String)
        clientID = clID
        clientSecret = ""
        myPin = ""
        imgToken = New Token
        LastImageLink = ""
        UseClipboard = True
        AnonOnly = True
    End Sub


    Private clientID As String
    Private clientSecret As String

    Private AnonOnly As Boolean = True

    ' tokens are not public
    Private imgToken As Token

    Public Property LastImageLink As String

    Public Property UseClipboard As Boolean

    ' precise moment when it expires for use in code
    Public ReadOnly Property TokenExpiry As DateTime
        Get
            If imgToken IsNot Nothing Then
                Return imgToken.Expiry
            Else
                Return Nothing
            End If
        End Get
    End Property

    Public Function GetExpiryCountdown() As String
        Return String.Format("{0:hh\:mm\:ss}", GetExpiryTimeRemaining)
    End Function

    ' time left as a TimeSpan
    Public Function GetExpiryTimeRemaining() As TimeSpan
        Dim ts As New TimeSpan(0)

        If imgToken Is Nothing Then
            Return ts
        End If

        If DateTime.Now > imgToken.Expiry Then
            Return ts
        Else
            ts = imgToken.Expiry - DateTime.Now
            Return ts
        End If

    End Function

    Public Function IsTokenValid() As Boolean

        If imgToken Is Nothing Then
            Return False
        End If

        If String.IsNullOrEmpty(imgToken.AcctUserName) Then
            Return False
        End If

        If imgToken.IsExpired Then
            Return False
        End If

        Return True

    End Function

    ' Currently, the PIN is set from a calling App.  Might be possible
    ' to feed the log in to imgUr to get a PIN
    Private myPin As String
    Public WriteOnly Property Pin As String
        Set(value As String)
            myPin = value
        End Set
    End Property


    ' Navigates to the web page.
    ' see wb_DocumentCompleted for code to 
    ' parse the PIN from the document
    Public Sub RequestPinBrowser(BrowserCtl As WebBrowser)

        If AnonOnly Then
            ' you do not need a PIN for Anon
            Throw New ApplicationException("A PIN is not needed for ANON Uploads")
            Exit Sub
        End If

        If BrowserCtl Is Nothing Then
            Throw New ArgumentException("Missing a valid WebBrowser reference")
            Exit Sub
        End If

        ' imgur API format
        ' https://api.imgur.com/oauth2/authorize?client_id=YOUR_CLIENT_ID&response_type=REQUESTED_RESPONSE_TYPE&state=APPLICATION_STATE

        Dim OAuthUrlTemplate = "https://api.imgur.com/oauth2/authorize?client_id={0}&response_type={1}&state={2}"
        Dim ReqURL As String = String.Format(OAuthUrlTemplate, clientID, "pin", "ziggy")

        BrowserCtl.Url = New Uri(ReqURL)
    End Sub


    Public Function GetAccessToken() As imgUrResults
        ' there are different types of token requests
        ' which vary only by the data submitted

        Dim sReq As String = String.Format("client_id={0}&client_secret={1}&grant_type=pin&pin={2}",
                                            clientID, clientSecret, myPin)
        If myPin = String.Empty Then
            Return imgUrResults.InvalidPIN
        End If

        If AnonOnly Then Return imgUrResults.InvalidRequest

        ' call generic token processor
        Return RequestToken(sReq)

    End Function

    ' request a Token 
    Private Function RequestToken(sRequest As String) As imgUrResults
        Dim url As String = "https://api.imgur.com/oauth2/token/"

        Dim myResult As imgUrResults = imgUrResults.OK

        ' create request for the URL, using POST method
        Dim request As WebRequest = WebRequest.Create(url)
        request.Method = "POST"

        ' convert the request, set content format, length
        Dim data As Byte() = System.Text.Encoding.UTF8.GetBytes(sRequest)
        request.ContentType = "application/x-www-form-urlencoded"
        request.ContentLength = data.Length

        ' write the date to request stream
        Dim dstream As Stream = request.GetRequestStream
        dstream.Write(data, 0, data.Length)
        dstream.Close()

        ' json used on the response and potential WebException
        Dim json As New JavaScriptSerializer()

        ' prepare for a response
        Dim response As WebResponse = Nothing
        Dim SvrResponses As Dictionary(Of String, Object)

        Try
            response = request.GetResponse
            ' convert status code to programmatic result
            myResult = GetResultFromStatus(CType(response, HttpWebResponse).StatusCode)

        Catch ex As WebException
            ' a bad/used pin will throw an exception
            Dim resp As String = New StreamReader(ex.Response.GetResponseStream()).ReadToEnd()

            SvrResponses = CType(json.DeserializeObject(resp.ToString), 
                                    Dictionary(Of String, Object))
            myResult = GetResultFromStatus(Convert.ToString(SvrResponses("status")))

        End Try

        'Console.WriteLine(CType(response, HttpWebResponse).StatusDescription)
        'Console.WriteLine(CType(response, HttpWebResponse).StatusCode)

        ' premature evacuation
        If myResult <> imgUrResults.OK Then
            If dstream IsNot Nothing Then
                dstream.Close()
                dstream.Dispose()
            End If
            If response IsNot Nothing Then
                response.Close()
            End If

            Return myResult
        End If

        ' read the response stream
        dstream = response.GetResponseStream
        Dim SvrResponseStr As String
        Using sr As StreamReader = New StreamReader(dstream)
            ' stream to string
            SvrResponseStr = sr.ReadToEnd
            'Console.WriteLine(SvrResponse)
        End Using

        ' close streams
        dstream.Close()
        dstream.Dispose()
        response.Close()

        Try
            ' use json serialier to parse the result(s)
            ' convert SvrRsponse to Dictionary
            SvrResponses = CType(json.DeserializeObject(SvrResponseStr), 
                                    Dictionary(Of String, Object))

            ' get stuff from Dictionary
            imgToken.AccessToken = Convert.ToString(SvrResponses("access_token"))
            imgToken.RefreshToken = Convert.ToString(SvrResponses("refresh_token"))
            imgToken.AcctUserName = Convert.ToString(SvrResponses("account_username"))

            ' convert expires_in to a point in time
            Dim nExp As Integer = Convert.ToInt32(Convert.ToString(SvrResponses("expires_in")))
            imgToken.Expiry = Date.Now.Add(New TimeSpan(0, 0, nExp))

            ' Pins are single use
            ' throw it away since it is no longer valid 
            myPin = ""

        Catch ex As Exception
            'MessageBox.Show(ex.Message)
            myResult = imgUrResults.TokenParseError
        End Try

        Return myResult


    End Function

    ' public interface to check params before trying to upload
    Public Function UploadImage(filename As String, Optional Anon As Boolean = False) As imgUrResults

        If AnonOnly Then
            Return DoImageUpLoad(filename, AnonOnly)
        Else
            If IsTokenValid() = False Then
                Return imgUrResults.InvalidToken
            End If
        End If

        ' should be the job of the calling app to test for FileExist
        Return DoImageUpLoad(filename, Anon)

    End Function

    ' actual file uploader
    Private Function DoImageUpLoad(fileName As String, Optional Anon As Boolean = False) As imgUrResults
        Dim result As imgUrResults = imgUrResults.OK
        LastImageLink = ""

        Try
            ' create a WebClient 
            Using wc = New Net.WebClient()
                ' read image
                Dim values = New NameValueCollection() From
                        {
                            {"image", Convert.ToBase64String(File.ReadAllBytes(fileName))}
                        }
                ' type of headers depends on whether this is an ANON or ACCOUNT upload
                If Anon Then
                    wc.Headers.Add("Authorization", "Client-ID " + clientID)
                Else
                    wc.Headers.Add("Authorization", "Bearer " & imgToken.AccessToken)
                End If

                ' upload, get response
                Dim response = wc.UploadValues("https://api.imgur.com/3/upload.xml", values)

                ' read response converting byte array to stream
                Using sr As New StreamReader(New MemoryStream(response))
                    Dim uplStatus As String
                    Dim SvrResponse As String = sr.ReadToEnd

                    Dim xdoc As XDocument = XDocument.Parse(SvrResponse)
                    ' get the status of the request
                    uplStatus = xdoc.Root.Attribute("status").Value
                    result = GetResultFromStatus(uplStatus)

                    If result = imgUrResults.OK Then
                        LastImageLink = xdoc.Descendants("link").Value

                        ' only overwrite the server result status
                        If String.IsNullOrEmpty(LastImageLink) Then
                            ' avoid NRE elsewhere
                            LastImageLink = ""
                            ' we did something wrong parsing the result
                            ' but this one is kind of minor
                            result = imgUrResults.OtherAPIError
                        End If
                    End If

                End Using

                If UseClipboard AndAlso (result = imgUrResults.OK) Then
                    Clipboard.SetText(LastImageLink)
                End If

            End Using
        Catch ex As Exception
            Dim errMsg As String = ex.Message

            ' rate limit
            If ex.Message.Contains("429") Then
                result = imgUrResults.RateLimitError

                ' internal error
            ElseIf ex.Message.Contains("500") Then
                result = imgUrResults.ServerError

            End If
        End Try

        Return result
    End Function

    Private Function GetResultFromStatus(status As String) As imgUrResults

        Select Case status.Trim
            Case "200"
                Return imgUrResults.OK
            Case "400"
                Return imgUrResults.BadRequestFormat
            Case "401"
                Return imgUrResults.AuthorizationError
            Case "403"
                Return imgUrResults.Forbidden
            Case "404"
                Return imgUrResults.NotFound
            Case "429"
                Return imgUrResults.RateLimitError
            Case "500"
                Return imgUrResults.ServerError
            Case Else
                ' Stop - work out other returns
                Return imgUrResults.UknownStatus
        End Select
    End Function

    Private Function GetResultFromStatus(status As Int32) As imgUrResults
        ' some places we get a string, others an integer
        Return GetResultFromStatus(status.ToString)
    End Function

End Class

HOW TO USE IT

The process requires a web browser for the user to navigate and request a PIN. For testing/development, I used a WebBrowser control and snagged the PIN from the returned page.

Note: for testing, my imgUR account was setup as DESKTOP, since we are sending from a DESKTOP app. Also, this is for YOU sending images to YOUR account. There is not a way for OTHERS to upload to YOUR account without giving out your secret ID and/or embedding your master ImgUR Login and password in the App. That is how ImgUR designed it.

A. Create an imgUR object:

Friend imgUR As imgurAPI
imgUR = New imgurAPI(<your Client ID>,<your secret code>)

B. Get a Pin - Method One

' pass the app's WebBrowser Control
imgUR.RequestPinBrowser(wb)

This will take you to a imgur page where you must authorize the issue of a PIN for uploading to your account. Enter your Account Name, Password, Click ALLOW. A new page with the PIN will be displayed. Copy the PIN from the webpage to some other control which can feed it to the imgurAPI Class.

There is code below to parse the PIN page and get it into another control.

Method Two

  • Using your own external browser, go to

https://api.imgur.com/oauth2/authorize? client_id=YOUR_CLIENT_ID&response_type=pin&state=ziggy

  • Log In
  • Copy the PIN you receive into a TextBox or something to send it to the imgurAPI:
  • Set pin: imgUR.Pin = <<PIN YOU RECEIVED>>

The process is the same either way, just a matter of whether you want to have to include a WebBrowser control in your form. PINs are only good for a short time, so you must use it to get an access token right away.

C. Get Access token

' imgUrResults is an enum exposed by the class
Dim result As imgurAPI.imgUrResults = imgUR.RequestToken

Notes:

  • the imgUR class will retain the token
  • tokens currently expire in 1 hour (3600 seconds)

D: Upload a File
Upload using imgUR.UploadImage(filename, boolAnon)

Filename - the file to upload

boolAnon - Boolean flag. False = upload this file to your account vs the Anon general pool method.

Example:

' get token
Dim result As imgurAPI.imgUrResults = imgUR.RequestToken

' check result
If result = imgurAPI.imgUrResults.OK Then
    ' assumes the file exists
    imgUR.UploadImage("C:\Temp\London.jpg", False)
Else
    MessageBox.Show(String.Format("Error getting access token. Status:{0}",
        result.ToString))
End If

After the file uploads, the procedure looks for the link in the response. If the link can be parsed, it will be available from the LastImageLink property and pasted to the ClipBoard as well.

Misc Properties, Settings and Methods

LastImageLink (String) - URL of the last image uploaded

UseClipBoard (Bool) - When true, imgurAPI class posts the link to the uploaded image to the Clipboard

TokenExpiry (Date) - The DateTime that the current token expires

GetTokenTimeRemaining() As TimeSpan - A TimeSpan representing how long before the current token expires

Public Function GetTokenCountdown() As String - Formatted string of TimeRemaining

Public WriteOnly Property Pin As String - the PIN required to get an access token

Public Function IsTokenValid() As Boolean - is the current token valid

Public Function IsTokenExpired() As Boolean - simple Boolean version of TimeRemaining vs DateTime.Now

Notes

  • Tokens can be renewed or extended. But since they last for an hour, this seems plenty.
  • PINS are only good for a short time. Once a PIN is exchanged for a token the imgurAPI (this class) clears the PIN. If there is a problem getting the Token, you will have to get a new PIN first (or paste the last one if you just got it a few minutes ago).
  • Uploaded images are not visible to the world at large unless/until you change the setting on your account.
  • You can reset your SecretID (Settings -> Applications). If you do, you will need to also reset it for apps using this API class, and recompile (or read it from a config file).

If you use a WebBrowser control to get a PIN, you can add this code to the DocumentCompleted event to scrape the PIN from the HTML:

' wb is the control
Dim htmlDoc As System.Windows.Forms.HtmlDocument = wb.Document
Dim elP As System.Windows.Forms.HtmlElement = htmlDoc.GetElementById("pin")

If elP IsNot Nothing Then
    sPin = elP.GetAttribute("value")
    If String.IsNullOrEmpty(sPin) = False Then
       ' user has to push the button for `imgUR.Pin = tbPIN.Text`
       ' this is in case the HTML changes, the user can override
       ' and input the correct PIN
       Me.tbPIN.Text = sPin
    End If

End If


About the OAuth Model

this is unofficial - info learned from reading the docs and working with the API. Applies to imgur API v3 as of this date.

There is nothing automated about getting a PIN. One way or another you must navigate to a URL in a browser and enter your account name and Password to get a PIN. This is by design so that you, yourself, personally are authorizing some external app to access your account content.

Method One above uses a .NET WebBrowser control to do this. With this method we can be sure that both you and the imgur class are using the same Endpoint/URL because it sends you there via the browser control.

Method Two is just you go there in some browser, any browser. Log in, get a PIN, and paste it to the imgurAPI class.

No matter the method, the correct Endpoint/URL to use is:

https://api.imgur.com/oauth2/authorize?client_id=YOUR_CLIENT_ID&response_type=pin&state=foobar

Using a browser on the form using the imgurAPI class, we obviously we can be sure that both you and the class are using the same URL and ClientID. The code for DocumentComplete fetches the PIN into the TextBox only you still need to set it in the class:

myimgUR.PIN = tbPinCode.Text

PINS are single use, and expire.

So when developing especially, and you stop the code, add some stuff then rerun naturally, the code will no longer have the old Token or PIN. If the last PIN was recent and not submitted, you might not have to get a new one, but I find it is hard to remember if that is the case.

The class treats PINS as single use. Once a Token has been received, it clears out the variable since they have been used and are no longer valid.


Final Edit

  • Added an Anon Only mode

To use the class to upload ONLY in Anon mode (to the general site, not your account), the SecretID is not needed. For this, use the new constructor overload:

Public Sub New(clientID As String)

This sets the class to work an Anon ONLY and certain methods will return an error or throe an exception when using Account based methods such as GetToken. If you initialize it with just ClientID, it remains in AnonOnly mode until you recreate the object with the both the ClientID and SecretID.

There is no real reason to use it as AnonOnly (unless you do not have an account) since the UploadImage method allows you to specify it as an Anon upload by file:

Function UploadImage(filename As String, 
                     Optional Anon As Boolean = False) As imgUrResults

  • Revised/clarified the imgUrResults Enum

This is meant to be all-encompassing: some returns indicate a problem detected by the class, others are server responses which are simply passed along.

  • Removed IsTokenExpired

IsTokenValid is more thorough. There are other methods to get the time remaining or the actual Expiry.

  • Added assorted error trapping/handling
    • Check for a valid WebBrowser control when requesting a PIN
    • Refined the method used to get the server status code after an image is uploaded
    • Reworked some handling to give prioritize remote server status over class returns

.

这篇关于访问直通OAuth的imgUr(上传到用户帐户)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-12 05:43