【问题标题】:403 when trying to download a remote image尝试下载远程图像时出现 403
【发布时间】: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


【解决方案1】:

如前所述,一些托管商使用诸如 UserAgent 之类的标头来防止这种入侵:

这不起作用:

   val urls = """http://blog.zenika.com/themes/Zenika/img/zenika.gif"""
  val url = new URL(urls)
  val urlConnection = url.openConnection() 
  val inputStream = urlConnection.getInputStream()
  val bufferedReader = new BufferedReader(new InputStreamReader(inputStream))

这行得通:

val urls = """http://blog.zenika.com/themes/Zenika/img/zenika.gif"""
val url = new URL(urls)
val urlConnection = url.openConnection()   
urlConnection.setRequestProperty("User-Agent", """NING/1.0""") 
val inputStream = urlConnection.getInputStream()
val bufferedReader = new BufferedReader(new InputStreamReader(inputStream))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-25
    • 2017-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多