xmlHttp下载文件

时间:2014-06-03 10:03:39

标签: vba http-headers download xmlhttprequest

使用谷歌浏览器我填写表格,按下提交按钮后,一张传播表自动开始下载。我已经确定发送到服务器的POST但不知何故,当我从我的脚本发送相同的请求时,响应不是文件而是原始Web表单。请参阅以下Chrome中显示的请求:


远程地址: ****** - 请求网址: * -

请求方法:POST - 状态代码:200 OK - **

请求标题

-Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
-Accept-Encoding:gzip,deflate,sdch
-Accept-Language:en-GB,en-US;q=0.8,en;q=0.6
-Cache-Control:max-age=0
-Connection:keep-alive
-Content-Length:207
-Content-Type:application/x-www-form-urlencoded
-Cookie:JSESSIONID=*******; ssoLang=en
-Host:*******
-Origin:******
-Referer:*******
-User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36

查询字符串参数

表单数据:请求

响应标头

-Content-Disposition: filename="xxx.xlsx"
-Content-Type:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
-Date:Sat, 31 May 2014 14:28:25 GMT
-Server:Apache-Coyote/1.1 
-Transfer-Encoding:chunked 

我得到的回复标题不同:

-Cache-Control: no-cache, no-store
-Date: Sat, 31 May 2014 14:55:38 GMT
-Pragma: no-cache Transfer-Encoding: chunked
-Content-Type: text/html;charset=UTF-8 Expires: Thu, 01 Jan 1970 00:00:00 GMT
-Server: Apache-Coyote/1.1

我试图执行上述操作的脚本如下,有人可以指出这里有什么问题吗?

Sub Download_File()
    Dim localFile As String, URL As String, request As String
    localFile = ThisWorkbook.Path & "\test.xlsx"
    URL = ****SENSITIVE***
    Dim XMLreq As Object
    Set XMLreq = CreateObject("MSXML2.XMLHTTP")

    request = ****REQUEST*****


    Dim fileNum As Integer, bytes() As Byte
    With XMLreq
        .Open "POST", URL, False
        .setRequestHeader "Host", ****SENSITIVE***
        .setRequestHeader "Connection", "keep-alive"
        .setRequestHeader "Content-Length", "207"
        .setRequestHeader "Cache-Control", "max-age=0"
        .setRequestHeader "Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"
        .setRequestHeader "Origin", ****SENSITIVE***
        .setRequestHeader "User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36"
        .setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
        .setRequestHeader "Referer", ****SENSITIVE***
        .setRequestHeader "Accept-Encoding", "gzip,deflate,sdch"
        .setRequestHeader "Accept-Language", "en-GB,en-US;q=0.8,en;q=0.6"
        .setRequestHeader "Cookie", "JSESSIONID=****SENSITIVE***; ssoLang=en"
        .send (Escape(request))
    While .readyState <> 4: DoEvents: Wend
    If .Status = 200 Then
        Debug.Print .getAllResponseHeaders
        fileNum = FreeFile
        Open localFile For Binary Access Write As #fileNum
        bytes = .responseBody
        Put #fileNum, , bytes
        Close #fileNum
    Else
        MsgBox "XMLhttp POST error " & .statusText & vbCrLf & "Status = " & .Status & vbCrLf & "URL = " & URL
    End If
    End With
End Sub


Private Function Escape(ByVal URL As String) As String
    Dim i As Integer, BadChars As String
    BadChars = "<>%=&!@#£$^()+{[}]|\;:'"",/?"
    For i = 1 To Len(BadChars)
        URL = Replace(URL, Mid(BadChars, i, 1), "%" & Hex(Asc(Mid(BadChars, i, 1))))
    Next i
    URL = Replace(URL, " ", "+")
    Escape = URL
End Function

1 个答案:

答案 0 :(得分:1)

这不是一个完整的答案,而更像是评论。我没有足够的声誉发表评论。

当某些检查或身份验证失败时,响应看起来会重定向到Web表单。你检查了JSESSIONID cookie吗?每次登录服务器时都应该有所不同。一旦您手动登录然后捕获JSESSIONID cookie(使用Fiddler作为Alex提到)或在浏览器地址栏中键入javascript:alert(document.cookie);并按Enter键,您就可以重用相同的会话令牌。

同时检查内容长度以确保url编码的内容长度与此值匹配。您可以使用Fiddler中的composer功能来测试对服务器的POST查询,以使请求参数正确。

BTW,Fiddler安装文件夹可以复制到USB记忆棒并用作便携式安装。你也可以尝试一下。

编辑:进一步看,问题似乎是该网站需要一个正确的Referer标头来发送excel文件。由于无法为XMLHttp请求设置Referer等不安全的标头,这可能会导致服务器端身份验证失败,并且可能会向您发送初始登录页面,即此处的Web表单。请检查此answer here