【发布时间】:2014-05-22 10:04:19
【问题描述】:
我正在尝试从一些网址下载图片。对于某些图片,它可以正常工作,但对于其他图片,我会收到 403 错误。
比如这个:http://blog.zenika.com/themes/Zenika/img/zenika.gif
此图片访问不需要任何身份验证。您可以单击链接并验证它是否可用于您的浏览器并显示 200 状态代码。
以下代码产生异常:new java.net.URL(url).openStream()。 org.apache.commons.io.FileUtils.copyURLToFile(new java.net.URL(url), tmp) 相同,它在底层使用相同的 openStream() 方法。
java.io.IOException: Server returned HTTP response code: 403 for URL: http://blog.zenika.com/themes/Zenika/img/zenika.gif
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1626) ~[na:1.7.0_45]
at java.net.URL.openStream(URL.java:1037) ~[na:1.7.0_45]
at services.impl.DefaultStampleServiceComponent$RemoteImgUrlFilter$class.downloadAsTemporaryFile(DefaultStampleServiceComponent.scala:548) [classes/:na]
at services.impl.DefaultStampleServiceComponent$RemoteImgUrlFilter$class.services$impl$DefaultStampleServiceComponent$RemoteImgUrlFilter$$handleImageUrl(DefaultStampleServiceComponent.scala:523) [classes/:na]
我使用 Scala / Play 框架进行开发。我尝试使用内置的 AsyncHttpClient。
// TODO it could be better to use itetarees on the GET call becase I think AHC load the whole body in memory
WS.url(url).get.flatMap { res =>
if (res.status >= 200 && res.status < 300) {
val bodyStream = res.getAHCResponse.getResponseBodyAsStream
val futureFile = TryUtils.tryToFuture(createTemporaryFile(bodyStream))
play.api.Logger.info(s"Successfully downloaded file $filename with status code ${res.status}")
futureFile
} else {
Future.failed(new RuntimeException(s"Download of file $filename returned status code ${res.status}"))
}
} recover {
case NonFatal(e) => throw new RuntimeException(s"Could not downloadAsTemporaryFile url=$url", e)
}
使用此 AHC 代码,它可以正常工作。有人可以解释这种行为以及为什么我在使用 URL.openStream() 方法时出现 403 错误吗?
【问题讨论】:
-
您发出多少请求?只是一个假设 - 也许你会因为超出请求限制而被踢?
-
@serejja 这只是一个请求,我在托管图像的不同服务上遇到了这个问题。也许你可以尝试自己在这个网址上做一个
new java.net.URL(url).openStream(),然后自己看看这不是垃圾邮件保护 -
一些图像主机试图避免机器人下载图像,所以如果他们意识到请求不是从浏览器发送的,他们只会以 403 状态响应,尝试检查命令行的纯 curl 请求是否给你正确的图像
-
@biesior 如果我只使用
curl下载图像,问题中的URL 就可以正常工作。 -
@Carsten @biesior AHC 使用的默认用户代理似乎是
NING/1.0。我不知道openStream()使用的是哪个用户代理@
标签: java scala playframework-2.0