如何解决通过 WebRequest 下载带有 JSON 响应的文件作为重定向
我正在努力寻找通过 WebRequest 下载文件的方法。
API 非常简单。所以我有以下地址:
https://eprel.ec.europa.eu/api/products/tyres/381324/labels?format=PDF
在这种情况下,浏览器中会显示一个标签。
使用 /labels
我可以下载一个 zip 包。
对于 /labels?noDirect=true&format=PDF
,响应将是一个 200 OK
,其内容包含资源的 URL (\{address:label or fiche URL}
)。
使用代码:
Dim request As WebRequest = WebRequest.Create("https://eprel.ec.europa.eu/api/products/tyres/381324/labels?noredirect=true&format=PDF")
request.Credentials = CredentialCache.DefaultCredentials
Dim response As WebResponse = request.GetResponse()
Console.WriteLine(CType(response,HttpWebResponse).StatusDescription)
Console.WriteLine(response)
Using dataStream As Stream = response.GetResponseStream()
Dim reader As New StreamReader(dataStream)
Dim responsefromServer As String = reader.ReadToEnd()
Console.WriteLine(responsefromServer)
End Using
我收到了 OK 响应,但没有收到用于下载标签的 URL。
此外,如果我只使用 /labels?format=PDF
,我将无法保护显示的 PDF。
我也尝试过 Selenium,但这个解决方案很慢。所以我更愿意坚持使用 WebRequest。
也许有人可以帮忙。
解决方法
API 有 2 路响应,基于请求的 URI:
- 如果您的 URI 是查询,则为
https://eprel.ec.europa.eu/api/products/tyres/381324/labels?format=PDF
响应是一个 JSON,它指定一个 URL 片段来替换查询,以构建直接资源的新 URI。 但它也会将WebResponse.ResourceUri
地址更改为此确切位置。不要使用?noDirect=true
选项。 - 如果您指定直接地址,如 https://eprel.ec.europa.eu/label/Label_381324.pdf
ResponseStream 将包含要下载的数据。
注意:这是一个二进制文件,您不能使用 StreamReader
读取二进制数据。
这里有两种方法可以将您的 PDF 文件下载为字节数组。GetPDFResourceAsync()
采用查询形式的 Uri,获取响应,然后调用第二个方法 GetPDFResourceDirectAsync()
,传递它从服务器收到的 WebResponse.ResourceUri
。
如果你想给我们查询URI,就调用GetPDFResourceAsync()
,如果你想直接使用资源URI,就调用GetPDFResourceDirectAsync()
。
InitializeWebRequest()
方法是初始化 HttpWebRequest 的实用方法。没有它,GetPDFResourceAsync()
将无法工作,因为服务器需要一个 User-Agent
标头集和一个压缩方法(否则你会得到垃圾)。
现在,这些方法返回一个字节数组(PDF 文件数据)。
您可以使用 File.WriteAllBytes() 方法将其存储到光盘。例如:
' Indirect method,using a URI query
Dim pdfBytes = Await GetPDFResourceAsync(New Uri("https://eprel.ec.europa.eu/api/products/tyres/381324/labels?format=PDF"))
' Direct method,using a resource URI
Dim pdfBytes = Await GetPDFResourceDirectAsync(New Uri("https://eprel.ec.europa.eu/label/Label_381324.pdf"))
Dim pdfFilePath = Path.Combine("[Some Directory]","Label381324.pdf")
File.WriteAllBytes(pdfFilePath,pdfBytes)
工作方法:
如果您不想/不能使用 async
方法,只需从任何地方删除 async
和 await
(包括方法名称),您将拥有同步代码。
Public Async Function GetPDFResourceAsync(resourceUri As Uri) As Task(Of Byte())
Dim request = WebRequest.CreateHttp(resourceUri)
InitializeWebRequest(request)
Using locResponse As HttpWebResponse = DirectCast(Await request.GetResponseAsync(),HttpWebResponse)
If locResponse.StatusCode = HttpStatusCode.OK Then
Return Await GetPDFResourceDirect(locResponse.ResponseUri)
Else
Return Nothing
End If
End Using
End Function
Public Async Function GetPDFResourceDirectAsync(resourceUri As Uri) As Task(Of Byte())
Dim request = WebRequest.CreateHttp(resourceUri)
InitializeWebRequest(request)
Dim buffersize As Integer = 132072
Dim buffer As Byte() = New Byte(buffersize - 1) {}
Dim dataResponse = DirectCast(Await request.GetResponseAsync(),HttpWebResponse)
If dataResponse.StatusCode = HttpStatusCode.OK Then
Using responseStream As Stream = dataResponse.GetResponseStream(),mStream As MemoryStream = New MemoryStream()
Dim read As Integer = 0
Do
read = Await responseStream.ReadAsync(buffer,buffer.Length)
Await mStream.WriteAsync(buffer,read)
Loop While read > 0
Return mStream.ToArray()
End Using
End If
Return Nothing
End Function
Private Sub InitializeWebRequest(request As HttpWebRequest)
request.UserAgent = "Mozilla/5.0 (Windows NT 10; WOW64; Trident/7.0; rv:11.0) like Gecko"
request.AutomaticDecompression = DecompressionMethods.GZip Or DecompressionMethods.Deflate
request.Headers.Add(HttpRequestHeader.AcceptEncoding,"gzip,deflate;q=0.8")
request.Headers.Add(HttpRequestHeader.CacheControl,"no-cache")
End Sub
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。