VB.NET - 多部分表单上传不起作用。怎么了?
我尝试搜索,发现有人编写了一个多部分表单上传器。
虽然它有一个错误:它传输了 url 中的所有 - 据称 - POST 值。但 Web 应用程序不喜欢这一点 - 不知何故。
它全部
POST /index.php?page=post&s=add&title=test&tags=testtags HTTP/1.1
并且只将文件添加到帖子内容中。
我尝试使用浏览器提交,结果如下:
POST /index.php?page=post&s=add HTTP/1.1
Host: gelbooru.com
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/532.0 (KHTML, like Gecko) Chrome/3.0.195.38 Safari/532.0
Referer: http://gelbooru.com/index.php?page=post&s=add
Content-Length: 54851
Cache-Control: max-age=0
Origin: http://gelbooru.com
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryFqdVQ+1blrPMX2py
Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Encoding: gzip,deflate,sdch
Cookie: __utmz=52483902.1258558959.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none);user_id=7382; pass_hash=lolpasswordcensored; __utma=52483902.1527465380.1258558959.1261431208.1261504455.7; __utmc=52483902; __utmb=52483902.1.10.1261504455
Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
------WebKitFormBoundaryFqdVQ+1blrPMX2py
Content-Disposition: form-data; name="upload"; filename="001.jpg"
Content-Type: image/jpeg
IMGDATA
------WebKitFormBoundaryFqdVQ+1blrPMX2py
Content-Disposition: form-data; name="source"
------WebKitFormBoundaryFqdVQ+1blrPMX2py
Content-Disposition: form-data; name="title"
------WebKitFormBoundaryFqdVQ+1blrPMX2py
Content-Disposition: form-data; name="tags"
tagtests
------WebKitFormBoundaryFqdVQ+1blrPMX2py
Content-Disposition: form-data; name="rating"
e
------WebKitFormBoundaryFqdVQ+1blrPMX2py
Content-Disposition: form-data; name="submit"
Upload
------WebKitFormBoundaryFqdVQ+1blrPMX2py--
我用 IMGDATA 替换了图像数据字节以使其更短。
此上传已被接受。所以我尝试用 VB.NET 代码来模仿这个,我很快就会展示。 结果出来了:
POST /index.php?page=post&s=add& HTTP/1.1
Cookie: user_id=7382; pass_hash=lolpass_hashcensor;
Origin: http://gelbooru.com
Referer: http://gelbooru.com/index.php?page=post&s=add
Content-Type: multipart/form-data; boundary=----------8cc5152e90b3c60
Host: gelbooru.com
Content-Length: 243397
Expect: 100-continue
Connection: Keep-Alive
HTTP/1.1 100 Continue
----------8cc5152e90b3c60
Content-Disposition: form-data; name="tags"
tagtest
----------8cc5152e90b3c60
Content-Disposition: form-data; name="source"
----------8cc5152e90b3c60
Content-Disposition: form-data; name="rating"
e
----------8cc5152e90b3c60
Content-Disposition: form-data; name="title"
----------8cc5152e90b3c60
Content-Disposition: form-data; name="submit"
Upload
----------8cc5152e90b3c60
Content-Disposition: form-data; name="upload"; filename="1017E.jpg"
Content-Type: application/octet-stream
FILE
----------8cc5152e90b3c60
但这并没有被接受。那么问题出在哪里呢?我还尝试将两个额外的(--)放在其他地方..最终,它没有改变任何东西。这是我用于传输的 VB.NET 代码的截图。 Uploader.Start 通过使用全局变量的线程启动上传过程。
Sub StartUploadJob(ByVal filepath As String, ByVal tags As String, ByVal title As String, ByVal source As String, ByVal rate As rating)
ContinueProgressLoop = True
processloop = New Threading.Thread(AddressOf ProgressLoopThread)
Uploader = New Threading.Thread(AddressOf UploadFileEx)
uploadfile = filepath
querystring("page") = "post"
querystring("s") = "add"
'http://gelbooru.com/index.php?page=dapi&s=post&q=index
'querystring("page") = "dapi"
'querystring("s") = "post"
'querystring("q") = "index"
'url = "http://gelbooru.com/index.php"
url = "http://sinni800.ath.cx/UploadTest.aspx"
'url = "http://gelbooru.com/ok.php"
fileFormName = "upload"
contenttype = "application/octet-stream"
uploadstrings("tags") = tags
uploadstrings("source") = source
uploadstrings("rating") = rate.ToString
uploadstrings("title") = title
'querystring("user_id") = My.Settings("user_id")
'querystring("pass_hash") = My.Settings("pass_hash")
uploadstrings("submit") = "Upload"
working = True
cookies = New CookieContainer()
'cookies.Add(My.Settings.cookies)
Uploader.Start()
processloop.Start()
End Sub
Dim uploadstrings As New NameValueCollection
Dim uploadfile As String : Dim url As String : Dim fileFormName As String : Dim contenttype As String : Dim querystring As New NameValueCollection : Dim cookies As CookieContainer
Function UploadFileEx() '(ByVal uploadfile As String, ByVal url As String, ByVal fileFormName As String, ByVal contenttype As String, ByVal querystring As NameValueCollection, ByVal cookies As CookieContainer) As String
If (fileFormName Is Nothing) OrElse (fileFormName.Length = 0) Then
fileFormName = "file"
End If
If (contenttype Is Nothing) OrElse (contenttype.Length = 0) Then
contenttype = "application/octet-stream"
End If
Dim postdata As String
postdata = "?"
If querystring IsNot Nothing Then
For Each key As String In querystring.Keys
postdata += (key & "=") + querystring.[Get](key) & "&"
Next
End If
Dim uri As New Uri(url + "?page=post&s=add")
Dim boundary As String = "----------" & DateTime.Now.Ticks.ToString("x")
Dim webrequest__1 As HttpWebRequest = DirectCast(WebRequest.Create(uri), HttpWebRequest)
'webrequest__1.CookieContainer = cookies
webrequest__1.Headers(HttpRequestHeader.Cookie) = My.Settings.cookie_string
webrequest__1.Headers.Add("Origin", "http://gelbooru.com")
webrequest__1.Referer = "http://gelbooru.com/index.php?page=post&s=add"
webrequest__1.ContentType = "multipart/form-data; boundary=" & boundary
webrequest__1.Method = "POST"
' Build up the post message header
Dim sb As New StringBuilder()
For Each key As String In uploadstrings.Keys
' content-disposition: form-data; name="field1"
'content-type: text/plain
sb.Append(boundary & vbCrLf)
sb.Append("Content-Disposition: form-data; name=""" + key + """" & vbCrLf)
' sb.Append("content-type: text/plain" & vbCrLf)
sb.Append(vbCrLf)
sb.Append(uploadstrings(key))
sb.Append(vbCrLf)
Next
Dim close As Byte() = Encoding.UTF8.GetBytes("--")
sb.Append("--")
sb.Append(boundary)
sb.Append(vbCr & vbLf)
sb.Append("Content-Disposition: form-data; name=""")
sb.Append(fileFormName)
sb.Append("""; filename=""")
sb.Append(Path.GetFileName(uploadfile))
sb.Append("""")
sb.Append(vbCr & vbLf)
sb.Append("Content-Type: ")
sb.Append(contenttype)
sb.Append(vbCr & vbLf)
sb.Append(vbCr & vbLf)
Dim postHeader As String = sb.ToString()
Dim postHeaderBytes As Byte() = Encoding.UTF8.GetBytes(postHeader)
' Build the trailing boundary string as a byte array
' ensuring the boundary appears on a line by itself
Dim boundaryBytes As Byte() = Encoding.ASCII.GetBytes(vbCr & vbLf & boundary & "--" & vbCr & vbLf)
Dim fileStream As New FileStream(uploadfile, FileMode.Open, FileAccess.Read)
Dim length As Long = postHeaderBytes.Length + fileStream.Length + boundaryBytes.Length
webrequest__1.ContentLength = length
Dim requestStream As Stream = webrequest__1.GetRequestStream()
Dim fulllength As Integer = postHeaderBytes.Length + fileStream.Length + boundaryBytes.Length
RaiseEvent TextMessage("")
' Write out our post header
RaiseEvent TextMessage("Write out our post header")
requestStream.Write(postHeaderBytes, 0, postHeaderBytes.Length)
progress = New Progress_Struct(100 / fulllength * postHeaderBytes.Length, postHeaderBytes.Length, fulllength)
' Write out the file contents
RaiseEvent TextMessage("Write out the file contents")
Dim buffer As Byte() = New [Byte](CUInt(Math.Min(4096, CInt(fileStream.Length))) - 1) {}
Dim bytesRead As Integer = 0
While (InlineAssignHelper(bytesRead, fileStream.Read(buffer, 0, buffer.Length))) <> 0
requestStream.Write(buffer, 0, bytesRead)
Progress = New Progress_Struct(100 / fulllength * (Progress.bytes_read + buffer.Length), Progress.bytes_read + buffer.Length, fulllength)
End While
RaiseEvent TextMessage("bytesRead = " + bytesRead.ToString)
RaiseEvent TextMessage("postHeaderBytes.length = " + postHeaderBytes.Length.ToString)
RaiseEvent TextMessage("Main File bytes written")
' Write out the trailing boundary
requestStream.Write(boundaryBytes, 0, boundaryBytes.Length)
Progress = New Progress_Struct(100 / fulllength * (Progress.bytes_read + boundaryBytes.Length), Progress.bytes_read + boundaryBytes.Length, fulllength)
Dim responce As WebResponse
Try
RaiseEvent TextMessage("Trying normal response...")
responce = webrequest__1.GetResponse()
Catch ex As Net.WebException
RaiseEvent TextMessage("ERROR " + ex.Status.ToString + " Trying to get Error response.")
responce = ex.Response
End Try
Dim s As Stream = responce.GetResponseStream()
Dim sr As New StreamReader(s)
ContinueProgressLoop = False
Dim returnstr As String = sr.ReadToEnd()
'SendHtmlMessage(returnstr)
RaiseEvent ProgressChange(Progress)
RaiseEvent UploadFinished(returnstr)
RaiseEvent TextMessage("Working FALSE")
working = False
Return returnstr
End Function
我希望任何人都可以帮助我解决这个问题。我不知道出了什么问题。
它应该返回带有重定向的“上传成功”消息,但它只返回上传页面本身。我用网络嗅探器检查过。
I tried searching and found out that someone has written a multipart form uploader.
Though it had one thing wrong: It transfered all the - supposedly - POST values in the url.. Which the web application doesn't like - somehow.
It went all
POST /index.php?page=post&s=add&title=test&tags=testtags HTTP/1.1
And only added the file into the post content.
I tried submitting with a browser, and this came out:
POST /index.php?page=post&s=add HTTP/1.1
Host: gelbooru.com
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/532.0 (KHTML, like Gecko) Chrome/3.0.195.38 Safari/532.0
Referer: http://gelbooru.com/index.php?page=post&s=add
Content-Length: 54851
Cache-Control: max-age=0
Origin: http://gelbooru.com
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryFqdVQ+1blrPMX2py
Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Encoding: gzip,deflate,sdch
Cookie: __utmz=52483902.1258558959.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none);user_id=7382; pass_hash=lolpasswordcensored; __utma=52483902.1527465380.1258558959.1261431208.1261504455.7; __utmc=52483902; __utmb=52483902.1.10.1261504455
Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
------WebKitFormBoundaryFqdVQ+1blrPMX2py
Content-Disposition: form-data; name="upload"; filename="001.jpg"
Content-Type: image/jpeg
IMGDATA
------WebKitFormBoundaryFqdVQ+1blrPMX2py
Content-Disposition: form-data; name="source"
------WebKitFormBoundaryFqdVQ+1blrPMX2py
Content-Disposition: form-data; name="title"
------WebKitFormBoundaryFqdVQ+1blrPMX2py
Content-Disposition: form-data; name="tags"
tagtests
------WebKitFormBoundaryFqdVQ+1blrPMX2py
Content-Disposition: form-data; name="rating"
e
------WebKitFormBoundaryFqdVQ+1blrPMX2py
Content-Disposition: form-data; name="submit"
Upload
------WebKitFormBoundaryFqdVQ+1blrPMX2py--
I replaced the image data bytes with IMGDATA to make it shorter.
This upload was accepted. So I tried to imitate this with VB.NET code I will show soon.
This came out:
POST /index.php?page=post&s=add& HTTP/1.1
Cookie: user_id=7382; pass_hash=lolpass_hashcensor;
Origin: http://gelbooru.com
Referer: http://gelbooru.com/index.php?page=post&s=add
Content-Type: multipart/form-data; boundary=----------8cc5152e90b3c60
Host: gelbooru.com
Content-Length: 243397
Expect: 100-continue
Connection: Keep-Alive
HTTP/1.1 100 Continue
----------8cc5152e90b3c60
Content-Disposition: form-data; name="tags"
tagtest
----------8cc5152e90b3c60
Content-Disposition: form-data; name="source"
----------8cc5152e90b3c60
Content-Disposition: form-data; name="rating"
e
----------8cc5152e90b3c60
Content-Disposition: form-data; name="title"
----------8cc5152e90b3c60
Content-Disposition: form-data; name="submit"
Upload
----------8cc5152e90b3c60
Content-Disposition: form-data; name="upload"; filename="1017E.jpg"
Content-Type: application/octet-stream
FILE
----------8cc5152e90b3c60
This got NOT accepted though. So what was the problem? I also tried putting the two extra (--) somewhere else.. And in the end, it didn't change anything. This is the cutout of the VB.NET code I used for transmitting. The Uploader.Start starts the upload process through a thread which uses the global variables.
Sub StartUploadJob(ByVal filepath As String, ByVal tags As String, ByVal title As String, ByVal source As String, ByVal rate As rating)
ContinueProgressLoop = True
processloop = New Threading.Thread(AddressOf ProgressLoopThread)
Uploader = New Threading.Thread(AddressOf UploadFileEx)
uploadfile = filepath
querystring("page") = "post"
querystring("s") = "add"
'http://gelbooru.com/index.php?page=dapi&s=post&q=index
'querystring("page") = "dapi"
'querystring("s") = "post"
'querystring("q") = "index"
'url = "http://gelbooru.com/index.php"
url = "http://sinni800.ath.cx/UploadTest.aspx"
'url = "http://gelbooru.com/ok.php"
fileFormName = "upload"
contenttype = "application/octet-stream"
uploadstrings("tags") = tags
uploadstrings("source") = source
uploadstrings("rating") = rate.ToString
uploadstrings("title") = title
'querystring("user_id") = My.Settings("user_id")
'querystring("pass_hash") = My.Settings("pass_hash")
uploadstrings("submit") = "Upload"
working = True
cookies = New CookieContainer()
'cookies.Add(My.Settings.cookies)
Uploader.Start()
processloop.Start()
End Sub
Dim uploadstrings As New NameValueCollection
Dim uploadfile As String : Dim url As String : Dim fileFormName As String : Dim contenttype As String : Dim querystring As New NameValueCollection : Dim cookies As CookieContainer
Function UploadFileEx() '(ByVal uploadfile As String, ByVal url As String, ByVal fileFormName As String, ByVal contenttype As String, ByVal querystring As NameValueCollection, ByVal cookies As CookieContainer) As String
If (fileFormName Is Nothing) OrElse (fileFormName.Length = 0) Then
fileFormName = "file"
End If
If (contenttype Is Nothing) OrElse (contenttype.Length = 0) Then
contenttype = "application/octet-stream"
End If
Dim postdata As String
postdata = "?"
If querystring IsNot Nothing Then
For Each key As String In querystring.Keys
postdata += (key & "=") + querystring.[Get](key) & "&"
Next
End If
Dim uri As New Uri(url + "?page=post&s=add")
Dim boundary As String = "----------" & DateTime.Now.Ticks.ToString("x")
Dim webrequest__1 As HttpWebRequest = DirectCast(WebRequest.Create(uri), HttpWebRequest)
'webrequest__1.CookieContainer = cookies
webrequest__1.Headers(HttpRequestHeader.Cookie) = My.Settings.cookie_string
webrequest__1.Headers.Add("Origin", "http://gelbooru.com")
webrequest__1.Referer = "http://gelbooru.com/index.php?page=post&s=add"
webrequest__1.ContentType = "multipart/form-data; boundary=" & boundary
webrequest__1.Method = "POST"
' Build up the post message header
Dim sb As New StringBuilder()
For Each key As String In uploadstrings.Keys
' content-disposition: form-data; name="field1"
'content-type: text/plain
sb.Append(boundary & vbCrLf)
sb.Append("Content-Disposition: form-data; name=""" + key + """" & vbCrLf)
' sb.Append("content-type: text/plain" & vbCrLf)
sb.Append(vbCrLf)
sb.Append(uploadstrings(key))
sb.Append(vbCrLf)
Next
Dim close As Byte() = Encoding.UTF8.GetBytes("--")
sb.Append("--")
sb.Append(boundary)
sb.Append(vbCr & vbLf)
sb.Append("Content-Disposition: form-data; name=""")
sb.Append(fileFormName)
sb.Append("""; filename=""")
sb.Append(Path.GetFileName(uploadfile))
sb.Append("""")
sb.Append(vbCr & vbLf)
sb.Append("Content-Type: ")
sb.Append(contenttype)
sb.Append(vbCr & vbLf)
sb.Append(vbCr & vbLf)
Dim postHeader As String = sb.ToString()
Dim postHeaderBytes As Byte() = Encoding.UTF8.GetBytes(postHeader)
' Build the trailing boundary string as a byte array
' ensuring the boundary appears on a line by itself
Dim boundaryBytes As Byte() = Encoding.ASCII.GetBytes(vbCr & vbLf & boundary & "--" & vbCr & vbLf)
Dim fileStream As New FileStream(uploadfile, FileMode.Open, FileAccess.Read)
Dim length As Long = postHeaderBytes.Length + fileStream.Length + boundaryBytes.Length
webrequest__1.ContentLength = length
Dim requestStream As Stream = webrequest__1.GetRequestStream()
Dim fulllength As Integer = postHeaderBytes.Length + fileStream.Length + boundaryBytes.Length
RaiseEvent TextMessage("")
' Write out our post header
RaiseEvent TextMessage("Write out our post header")
requestStream.Write(postHeaderBytes, 0, postHeaderBytes.Length)
progress = New Progress_Struct(100 / fulllength * postHeaderBytes.Length, postHeaderBytes.Length, fulllength)
' Write out the file contents
RaiseEvent TextMessage("Write out the file contents")
Dim buffer As Byte() = New [Byte](CUInt(Math.Min(4096, CInt(fileStream.Length))) - 1) {}
Dim bytesRead As Integer = 0
While (InlineAssignHelper(bytesRead, fileStream.Read(buffer, 0, buffer.Length))) <> 0
requestStream.Write(buffer, 0, bytesRead)
Progress = New Progress_Struct(100 / fulllength * (Progress.bytes_read + buffer.Length), Progress.bytes_read + buffer.Length, fulllength)
End While
RaiseEvent TextMessage("bytesRead = " + bytesRead.ToString)
RaiseEvent TextMessage("postHeaderBytes.length = " + postHeaderBytes.Length.ToString)
RaiseEvent TextMessage("Main File bytes written")
' Write out the trailing boundary
requestStream.Write(boundaryBytes, 0, boundaryBytes.Length)
Progress = New Progress_Struct(100 / fulllength * (Progress.bytes_read + boundaryBytes.Length), Progress.bytes_read + boundaryBytes.Length, fulllength)
Dim responce As WebResponse
Try
RaiseEvent TextMessage("Trying normal response...")
responce = webrequest__1.GetResponse()
Catch ex As Net.WebException
RaiseEvent TextMessage("ERROR " + ex.Status.ToString + " Trying to get Error response.")
responce = ex.Response
End Try
Dim s As Stream = responce.GetResponseStream()
Dim sr As New StreamReader(s)
ContinueProgressLoop = False
Dim returnstr As String = sr.ReadToEnd()
'SendHtmlMessage(returnstr)
RaiseEvent ProgressChange(Progress)
RaiseEvent UploadFinished(returnstr)
RaiseEvent TextMessage("Working FALSE")
working = False
Return returnstr
End Function
I hope anybody can help me with this. I can't figure out what is wrong.
It should return a "Upload Success" message with a redirect, but it only returns the upload page itself. I checked with a network sniffer.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您为什么不看看
System.Net.WebClient
类呢? http://msdn.microsoft.com/en-us/ library/system.net.webclient.aspx 这样你就不必担心格式化 POST 数据,你只需调用WebClient.UploadFile()
: http://msdn.microsoft.com/en-us/library/36s52zhs.aspxWhy don't you take a look at
System.Net.WebClient
class instead? http://msdn.microsoft.com/en-us/library/system.net.webclient.aspx This way you do not have to worry about formatting the POST data, you just callWebClient.UploadFile()
: http://msdn.microsoft.com/en-us/library/36s52zhs.aspx