如何使用PHP插入查询将当前时间戳插入到MySQL数据库中(How to insert the current timestamp into MySQL database using a PHP insert query)
在我的MySQL数据库中,我有一个表的结构
username - varchar insert_time - timestamp
这个表是使用phpMyAdmin工具在MySQL中创建的,对于
insert_time
列,我已经将默认值提到了0000-00-00 00:00:00
。现在的问题是,使用PHP脚本,我必须使用当前时间戳更新此默认值。
我尝试执行以下PHP代码:
$update_query = 'UPDATE db.tablename SET insert_time=now() '. 'WHERE username='.$somename;
当PHP脚本运行时,它失败,并且无法将任何东西插入数据库。
我究竟做错了什么?
In my MySQL database, I have a table with structure
username - varchar insert_time - timestamp
This table was created in MySQL using the phpMyAdmin tool and for the
insert_time
column, I have mentioned default value as0000-00-00 00:00:00
.Now the problem is, I have to update this default value with the current timestamp later on, using a PHP script.
I tried doing the following PHP code:
$update_query = 'UPDATE db.tablename SET insert_time=now() '. 'WHERE username='.$somename;
When the PHP script is run, it fails, and is unable to insert anything into the database.
What am I doing wrong?
原文:https://stackoverflow.com/questions/6075926
最满意答案
这很长,因为它或多或少是一个完整的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
如何使用它
该过程需要Web浏览器以供用户导航和请求PIN。 对于测试/开发,我使用了一个WebBrowser控件并从返回的页面中获取了PIN。
注意:为了进行测试,我的imgUR帐户设置为DESKTOP,因为我们是从DESKTOP应用程序发送的。 此外,这是您将图像发送到您的帐户。 其他人无法在不泄露您的密码和/或在应用程序中嵌入您的主ImgUR登录名和密码的情况下上传到您的帐户。 这就是ImgUR设计它的方式。
A.创建一个imgUR对象:
Friend imgUR As imgurAPI imgUR = New imgurAPI(<your Client ID>,<your secret code>)
B.获得一个Pin - 方法一
' pass the app's WebBrowser Control imgUR.RequestPinBrowser(wb)
这会将您带到一个imgur页面,您必须在其中授权发布PIN才能上传到您的帐户。 输入您的帐户名,密码,单击“允许”。 将显示带有PIN的新页面。 将PIN从网页复制到其他控件,该控件可将其提供给imgurAPI类。
下面有代码来解析PIN页面并将其转换为另一个控件。
方法二
- 使用您自己的外部浏览器,转到
https://api.imgur.com/oauth2/authorize? client_id=YOUR_CLIENT_ID&response_type=pin&state=ziggy
- 登录
- 将您收到的PIN复制到
TextBox
或其他内容以将其发送到imgurAPI:- 设置图钉:
imgUR.Pin = <<PIN YOU RECEIVED>>
无论哪种方式都是相同的,只需要在表单中包含WebBrowser控件即可。 PIN只能在短时间内使用,因此您必须立即使用它来获取访问令牌。
C.获取访问令牌
' imgUrResults is an enum exposed by the class Dim result As imgurAPI.imgUrResults = imgUR.RequestToken
笔记:
- imgUR类将保留令牌
- 令牌目前在1小时(3600秒)到期
D:上传文件
使用imgUR.UploadImage(filename, boolAnon)
上传imgUR.UploadImage(filename, boolAnon)
文件名 - 要上载的文件
boolAnon - 布尔标志。 False =将此文件上传到您的帐户,而不是Anon常规池方法。
例:
' 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
文件上载后,该过程将在响应中查找链接。 如果可以解析链接,它将从
LastImageLink
属性中获得并粘贴到ClipBoard。其他属性,设置和方法
LastImageLink (String) - 上传的最后一张图片的URL
UseClipBoard (Bool) - 当为true时,imgurAPI类将上传图像的链接发布到剪贴板
TokenExpiry (Date) - 当前令牌到期的DateTime
GetTokenTimeRemaining ()As TimeSpan - 表示当前令牌到期前多长时间的TimeSpan
Public Function GetTokenCountdown() As String - TimeRemaining的格式化字符串
Public WriteOnly Property Pin As String - 获取访问令牌所需的PIN
Public Function IsTokenValid() As Boolean - 当前标记有效
Public Function IsTokenExpired ()As Boolean - TimeRemaining与DateTime.Now的简单布尔版本
笔记
- 令牌可以续订或扩展。 但由于它们持续了一个小时,这似乎很多。
- PIN码只在很短的时间内有用。 一旦PIN被交换为令牌,imgurAPI(此类)将清除PIN。 如果获取令牌时出现问题,则必须先获取新的PIN(如果几分钟前刚刚获得,则粘贴最后一个)。
- 除非/直到您更改帐户设置,否则整个世界都无法看到上传的图片。
- 您可以重置您的SecretID(设置 - >应用程序)。 如果这样做,您还需要为使用此API类的应用重置它,并重新编译(或从配置文件中读取)。
如果使用
WebBrowser
控件获取PIN,则可以将此代码添加到DocumentCompleted
事件以从HTML中删除PIN:' 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
关于OAuth模型
这是非官方的 - 从阅读文档和使用API学到的信息。 适用于此日期的imgur API v3。
获取PIN码没有任何自动化。 无论如何,您必须导航到浏览器中的URL并输入您的帐户名和密码才能获得PIN。 这是设计使您,您自己,个人正在授权一些外部应用程序访问您的帐户内容。
上面的方法一使用.NET WebBrowser控件来执行此操作。 使用此方法,我们可以确保您和imgur类都使用相同的Endpoint / URL,因为它通过浏览器控件将您发送到那里。
方法二只是你在某个浏览器,任何浏览器去那里。 登录,获取PIN,然后将其粘贴到imgurAPI类。
无论方法如何,要使用的正确端点/ URL是:
https://api.imgur.com/oauth2/authorize?client_id=YOUR_CLIENT_ID&response_type=pin&state=foobar
使用imgurAPI类在表单上使用浏览器,显然我们可以确定您和类都使用相同的URL和ClientID。
DocumentComplete
的代码只需将PIN提取到TextBox中,您仍然需要在类中设置它:myimgUR.PIN = tbPinCode.Text
PIN码是一次性使用,并且到期。
所以特别是在开发时,你停止代码,添加一些东西然后自然重新运行,代码将不再有旧的令牌或PIN。 如果最后一个PIN是最近的并且未提交,您可能不需要获得新的PIN,但我发现很难记住是否是这种情况。
该课程将PINS视为一次性使用。 收到令牌后,它会清除变量,因为它们已被使用且不再有效。
最终编辑
- 添加了仅限Anon模式
要使用该类仅以匿名模式(一般网站,而不是您的帐户)上传,不需要SecretID。 为此,使用新的构造函数重载:
Public Sub New(clientID As String)
这会将类设置为仅使用Anon,并且在使用基于帐户的方法(如
GetToken
时,某些方法将返回错误或引发异常。 如果仅使用ClientID初始化它,它将保持AnonOnly模式,直到您使用ClientID和SecretID重新创建对象。没有任何理由将其用作AnonOnly(除非您没有帐户),因为UploadImage方法允许您将其指定为按文件匿名上传:
Function UploadImage(filename As String, Optional Anon As Boolean = False) As imgUrResults
- 修改/澄清了imgUrResults Enum
这意味着无所不包:一些返回表示类检测到的问题,另一些返回是简单传递的服务器响应。
- 删除了
IsTokenExpired
IsTokenValid
更彻底。 还有其他方法可以获得剩余时间或实际到期时间。
- 添加了各种错误捕获/处理
- 请求PIN时检查有效的WebBrowser控件
- 改进了上传图像后用于获取服务器状态码的方法
- 重新设计了一些处理,以便在类返回时优先考虑远程服务器状态
。
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 usingimgUR.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 theDocumentCompleted
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
.
相关问答
更多-
您将需要每个帐户的访问令牌。 您可以通过多种方式获取它们,例如,为每个帐户请求脱机访问并存储两个刷新令牌。 还有其他方法。 您需要详细说明要实现的行为。 You will need an access token for each account. There are various ways you can get them, for example request offline access for each account and store the two refresh tokens. Ther ...
-
这很长,因为它或多或少是一个完整的API: Public Class imgurAPI ' combination of this API and imgUR server responses Public Enum imgUrResults OK = 200 ' AKA Status200 ' errors WE return OtherAPIError = -1 ' ...
-
将参数prompt=select_account添加到您的授权请求中。 这将导致帐户选择器始终显示,即使用户仅登录到一个帐户。 用户将能够从他们的账户中进行选择,或者添加一个新账户。 例如: https : //accounts.google.com/o/oauth2/auth?redirect_uri=https%3A%2F%2Fdevelopers.google.com%2Foauthplayground&response_type=code&client_id=407408718192.apps.go ...
-
使用Volley将图像上传到IMGUR会返回TimeoutError(Uploading images to IMGUR using Volley returns TimeoutError)[2023-06-01]
更改请求上的DefaultRetryPolicy以具有更大的到期时间帧,因为上传图像可能会花一点时间。 另外,对于双重上传,请确保将max_retries设置为0。 new DefaultRetryPolicy(LONGER_TIMEOUT, 0, 0); Change the DefaultRetryPolicy on the Request to have a larger expiration time frame, since uploading an image can take a bit. A ... -
我几天前写过这样一个工具。 看看我的Imgur Bash脚本 。 请注意,您需要在imgur.com上手动注册应用程序并获取access_token , refresh_token , client_id和client_secret ,然后在出现提示时提供此信息。 此设置仅发生一次,并在需要时自动请求新的访问令牌。 如何获取令牌, 客户端ID和客户端密钥 : 创建一个Imgur帐户。 注册申请 。 您现在应该拥有客户端ID和客户端密钥 。 使用以下URL打开浏览器: https://api.imgur.co ...
-
Imgur阻止了我的IP?(Imgur block my IP?)[2021-09-24]
我有同样的问题。 显然“ 每小时每个IP地址有50个图像的上传限制 ”。 我不知道他们为什么不在主api.imgur.com页面上说明这一点,它是API的基本信息...... 希望这可以帮助。 I'm having the same issue. Apparently "there is an upload limit of 50 images per IP address per hour". I don't know why they don't state this on the main api.i ... -
似乎file.type未定义。 原因是您正在错误地使用jQuery.get函数的返回值。 此函数返回没有type属性的jqXHR对象。 It seems file.type is undefined. The reason for this is that you are using the return value of the jQuery.get function incorrectly. This function returns a jqXHR object which does not have ...
-
调用auth2.signIn()将始终提示用户登录,即使他们已经登录。在此之前,请检查他们是否已使用auth2.currentUser.get().isSignedIn() 。 这是您的代码的修改版本: function authorize(){ gapi.client.setApiKey(API_KEY); gapi.auth2.init({ client_id: CLIENT_ID, scope: SCOPES }).then(function(a ...
-
我想到了。 您需要使用imgur的oauth 2 api发送"BEARER"标头,而不是发送"CLIENT-ID"标头。 这允许您将图像发布到用户的帐户,而在我只提供客户端ID之前,这允许我发布匿名图像。 代码如下所示: client.Headers.Add("Authorization", "BEARER " + accessToken); I figured it out. Instead of sending a "CLIENT-ID" header, you need to send a "BEA ...
-
这是一个v3请求,但您没有使用SSL,这是必需的。 尝试设置 url = "https://api.imgur.com/3/upload.json" # ^ This is a v3 request, but you're not using SSL, which is mandatory. Try setting url = "https://api.imgur.com/3/upload.json" # ^