2017-01-19 2 views
1

약 10 초 동안 매 초마다 파일이 있는지 서버를 확인하고 싶습니다. 파일이 있으면 다운로드하십시오. 그것은 거기에 있지 않습니다. (404) 10 초 동안 최대 10 번까지 다시 시도하십시오. 내가 VBA에없는 보통 코드를 수행하지만, 여기에 간다 .. 내 다운로드 기능이 있습니다루프 내에서 'IXMLHTTPRequest'객체의 열기가 실패합니다.

Function DownloadFile(url As String, fileID As String) 

    ' Setup our path where we will save the downloaded file. 
    Dim fileSavePath As String 
    fileSavePath = Environ("USERPROFILE") & "\" & Environ("USERNAME") & "-123-" & fileID & ".xlsx" 

    ' Use Microsoft.XMLHTTP in order to setup a connection. 
    ' https://msdn.microsoft.com/en-us/library/ms535874(v=vs.85).aspx#methods 
    Dim WinHttpReq As Object 
    Set WinHttpReq = CreateObject("MSXML2.XMLHTTP") 
    ' Pass GET to the Open method in order to start the download of the file. 
    WinHttpReq.Open "GET", url, False ' method, http verb, async = false 

    ' Send our request: https://msdn.microsoft.com/en-us/library/ms536736(v=vs.85).aspx 
    WinHttpReq.send 

    ' Reset the url parameter to be the body of the response. 
    url = WinHttpReq.responseBody 

    ' WinHttpReq.Status holds the HTTP response code. 
    If WinHttpReq.Status = 200 Then 
     ' Setup an object to hold the binary stream of data (the file). 
     Set oStream = CreateObject("ADODB.Stream") 
     oStream.Open 
     ' Set type read only or not: https://msdn.microsoft.com/en-us/library/ms681553(v=vs.85).aspx 
     oStream.Type = 1 
     ' Write the binary data to WinHttpReq.responseBody 
     ' We can do this because we have confirmed a download via the response code (200). 
     oStream.Write WinHttpReq.responseBody 
     oStream.SaveToFile fileSavePath, 2 ' 2 = overwrites the existing file, 1 = will not. 
     ' We are done we the stream, close it. 
     oStream.Close 
     Debug.Print "File downloaded! File path: " & fileSavePath 
     DownloadFile = 1 
    End If 

    ' Handle if the file doesn't exist. 
    If WinHttpReq.Status = 404 Then 
     DownloadFile = 0 
    End If 

End Function 

을 그리고 나는 10 번이 기능을 호출하는 하위 있습니다

Sub Callee(url As String, fileID As String) 

    Dim i As Integer 
    i = 0 

    Do While i < 10 

     If DownloadFile(url, fileID) = 1 Then 
      Debug.Print "here" 
      i = 100 
     Else 
      Debug.Print fileID & " not found! Try number: " & i 
      i = i + 1 
      ' We didnt get the response we wanted, so we will wait one second and try again. 
      Application.Wait (Now + TimeValue("0:00:01")) 
     End If 

    Loop 

End Sub 

내 코드를 404 응답을 받으면 한 번만 실행됩니다. 코드가 루프를 시도 할 때 다시 내가 얻을 : 내 코드는 한 번만 루프를 통해 한 시간을 실행하는 이유

Method open of object IXMLHTTPReuest failed

내가 이해가 안 돼요. 나는 Set WinHttpReq = Nothing에 가비지 콜렉션의 일종을 돌봐주지 않았다. 그러나이 변수가 내 함수에 적용된다는 것을 알았지 만 ...

도움을 주셔서 감사합니다.

답변

1

죄송하지만이 질문과 대답은 오해의 소지가 있습니다. 코드는 url이 이진 데이터로 채워집니다 라인

' Reset the url parameter to be the body of the response. 
url = WinHttpReq.responseBody 

에 버그가 있습니다. 왜 이런 짓을하는? 물론 ByVal을 사용하면 매번 url의 새로운 사본을 얻을 수 있다는 것을 의미하지만이 작업을 수행하는 이유는 무엇입니까? 이 줄을 주석 처리하고 문제가 사라집니다.

이렇게 IMHO는 MSXML2.XMLHTTP 인스턴스 생성과 관련이 없으며 가비지 수집의 경우 url이 전달되지 않았습니다.

+0

당신은 절대적으로 옳습니다!전에 엄격하게 형식화 된 많은 언어를 입력하지 않았고 그 행은 실수입니다. 필자가 타이핑했을 때,''''WinHttpReq.responseBody''로 무엇인가를하고,'''url''을 그 때 의미가있는 것으로 다시 설정하는 아이디어가 있었지만 그것이 어울리지 않을 것이라고 생각합니다. 다른 유형의 변수. 그 점을 지적 해 주셔서 감사합니다! 적어도 나는 (내) 코드에 문제가 없다는 것을 알고있다. Upvoted. – jonathanbell

0

Callee 메서드에서 WinHttpReq을 만들고이 개체를 사용하여 요청을 보내 주시겠습니까? 예 :

Option Explicit 

Sub Callee(url As String, fileID As String) 

    ' Setup our path where we will save the downloaded file. 
    Dim fileSavePath As String 
    fileSavePath = Environ("USERPROFILE") & "\" & Environ("USERNAME") & "-123-" & fileID & ".xlsx" 

    ' Use Microsoft.XMLHTTP in order to setup a connection. 
    ' https://msdn.microsoft.com/en-us/library/ms535874(v=vs.85).aspx#methods 
    Dim WinHttpReq As Object 
    Set WinHttpReq = CreateObject("MSXML2.XMLHTTP") 
    ' Pass GET to the Open method in order to start the download of the file. 
    WinHttpReq.Open "GET", url, False ' method, http verb, async = false 

    Dim i As Integer 
    i = 0 

    Do While i < 10 

     If DownloadFile(url, fileID, fileSavePath, WinHttpReq) = 1 Then 
      Debug.Print "here" 
      Exit Do 
     Else 
      Debug.Print fileID & " not found! Try number: " & i 
      i = i + 1 
      ' We didnt get the response we wanted, so we will wait one second and try again. 
      Application.Wait (Now + TimeValue("0:00:01")) 
     End If 

    Loop 

End Sub 

Function DownloadFile(url As String, fileID As String, fileSavePath As String, WinHttpReq As Object) 
    ' Send our request: https://msdn.microsoft.com/en-us/library/ms536736(v=vs.85).aspx 
    WinHttpReq.send 

    ' Reset the url parameter to be the body of the response. 
    url = WinHttpReq.responseBody 

    ' WinHttpReq.Status holds the HTTP response code. 
    If WinHttpReq.Status = 200 Then 
     ' Setup an object to hold the binary stream of data (the file). 
     Dim oStream 
     Set oStream = CreateObject("ADODB.Stream") 
     oStream.Open 
     ' Set type read only or not: https://msdn.microsoft.com/en-us/library/ms681553(v=vs.85).aspx 
     oStream.Type = 1 
     ' Write the binary data to WinHttpReq.responseBody 
     ' We can do this because we have confirmed a download via the response code (200). 
     oStream.Write WinHttpReq.responseBody 
     oStream.SaveToFile fileSavePath, 2 ' 2 = overwrites the existing file, 1 = will not. 
     ' We are done we the stream, close it. 
     oStream.Close 
     Debug.Print "File downloaded! File path: " & fileSavePath 
     DownloadFile = 1 
    End If 

    ' Handle if the file doesn't exist. 
    If WinHttpReq.Status = 404 Then 
     DownloadFile = 0 
    End If 

End Function 
+0

음 ... 재미 있습니다! 나는 그런 식으로 XMLHTTP 메서드를 전달하는 것에 대해 생각하지 않았습니다. 불행히도 이런 식으로 코드를 작성하면''User defined type not defined'''가 발생합니다. VBA에서이 방법을 사용할 수 있습니까? – jonathanbell

+0

내가 분류했다고 생각해! 나는 이것을 알기 위해 VBA에서 코드를 작성하지는 않지만,''ByVal'' 키워드를 사용하여'''DownloadFile'''에 매개 변수를 전달해야합니다. 그래서''와 같습니다. Function DownloadFile (ByVal url As String , ByVal fileId As String)'''여기에서 문서를 찾았습니다 : https://msdn.microsoft.com/en-us/library/aa263527(v=vs.60).aspx 틀림없이, 저는 조금 당황 스럽지만 여전히 왜 이런 문제가 발생했는지 또는 루프가 한 번만 반복되는 이유를 이해하지 못합니다. – jonathanbell

+0

수정 된 답변보기 [Late Binding]을 사용하기 때문에 매개 변수의 유형이 Object 여야합니다 (https://support.microsoft.com/en-us/help/245115/using-early-binding-and-late-binding-in- 오토메이션). 왜 이런 행동이 일어 났는가? 처음에는'open'을 호출 한 다음 괜찮 았던'send'를 호출했습니다. 그런데 당신은'open'을 이미 호출했기 때문에 다시 실패했다. 나는'open'을 한 번 더 호출하는 것이 효과가 없을 것이라고 추측합니다. 따라서 제안서는 한 번 '열린'을 호출 한 다음 여러 번 보내고 결과를 처리합니다. HTH – dee