Scala 使用媒体URI从twilio下载媒体文件

Scala 使用媒体URI从twilio下载媒体文件,scala,playframework,playframework-2.0,twilio,Scala,Playframework,Playframework 2.0,Twilio,我在下载彩信时遇到问题 val url = https://api.twilio.com/2010-04-01/Accounts/xx/Messages/xx/Media/xx 提供的媒体url位于上述结构中 new URL(url) #> new File("file.png") !! //this fails, due to multiple redirects 当我在浏览器中打开URI时,重定向以 http://media.twiliocdn.com.s3-external-1.

我在下载彩信时遇到问题

val url = https://api.twilio.com/2010-04-01/Accounts/xx/Messages/xx/Media/xx
提供的媒体url位于上述结构中

new URL(url) #> new File("file.png") !! //this fails, due to multiple redirects
当我在浏览器中打开URI时,重定向以

http://media.twiliocdn.com.s3-external-1.amazonaws.com/xx/xx
第一个url->第二个url->上面的url;因此,总共有2个重定向

如果我用新的url尝试上面发布的代码片段,它会起作用。我确信这是因为多重重定向,代码片段一开始就不起作用

使用play frameworkscala时,我可以得到任何源示例来下载该文件。感谢您的帮助或指点。尝试了各种各样的例子,但仍然无法解决问题

一些发现=>

scala有类似的吗

更新:@millhouse

def fileDownloader(urls: String, location: String) = {

    import play.api.Play.current
    import scala.concurrent.ExecutionContext.Implicits.global

    // Make the request
    val futureResponse: Future[(WSResponseHeaders, Enumerator[Array[Byte]])] =
      WS.url(urls).withFollowRedirects(true).getStream()

    futureResponse.flatMap {
      case (headers, body) =>
        val file = new File(location)
        val outputStream = new FileOutputStream(file)

        // The iteratee that writes to the output stream
        val iteratee = Iteratee.foreach[Array[Byte]] { bytes =>
          outputStream.write(bytes)
        }

        // Feed the body into the iteratee
        (body |>>> iteratee).andThen {
          case result =>
            // Close the output stream whether there was an error or not
            outputStream.close()
            // Get the result or rethrow the error
            result.get
        }.map(_ => file)
    }
  }
正如play文档中所解释的,这是我到目前为止一直使用的方法(有效)。但是我需要一种同步方法,这意味着我需要在成功下载文件时执行另一个步骤。对不起,没有在前面澄清

更新2:以这种方式解决

        def fileDownloader(urls: String, location: String) = {

                    import play.api.Play.current
                    import scala.concurrent.ExecutionContext.Implicits.global

                    // Make the request
                    val futureResponse: Future[(WSResponseHeaders, Enumerator[Array[Byte]])] =
                      WS.url(urls).withFollowRedirects(true).getStream()

                     val downloadedFile: Future[File] = futureResponse.flatMap {
                      case (headers, body) =>
                        val file = new File(location)
                        val outputStream = new FileOutputStream(file)

                        // The iteratee that writes to the output stream
                        val iteratee = Iteratee.foreach[Array[Byte]] { bytes =>
                          outputStream.write(bytes)
                        }

                        // Feed the body into the iteratee
                        (body |>>> iteratee).andThen {
                          case result =>
                            // Close the output stream whether there was an error or not
                            outputStream.close()
                            // Get the result or rethrow the error
                            result.get
                        }.map(_ => file)
                    }
    downloadedFile.map{ fileIn =>
              //things needed to do
}
                  }

谢谢,

我没有使用Twilio MMS API,但是让Play Framework HTTP客户端遵循重定向应该非常简单,使用到客户端的:

val url = "https://api.twilio.com/2010-04-01/Accounts/xx/Messages/xx/Media/xx"

ws.url(url).withFollowRedirects(true).get().map { response =>
  val theBytes:Array[Byte] = response.bodyAsBytes // Play 2.4 and lower
  // ... save it  
}
请注意,上述代码适用于Play 2.4.x及更低版本。如果您使用的是当前最先进的技术,那么它会为您提供一个具有许多优秀功能方法的解决方案,但是如果您只想存储数据,您可能只想调用
toArray

ws.url(url).withFollowRedirects(true).get().map { response =>
  val theBytes:Array[Byte] = response.bodyAsBytes.toArray // Play 2.5
  // ... save it  
}

谢谢你的回答。但是,我似乎找不到与ws响应相关/适用的
bodyAsBytes
方法。我是否遗漏了任何进口或。。。。使用2.3.8 BTW感谢您的帮助@millhouse!如果您想要Twilio的感谢t恤,请发送电子邮件至mspeir@twilio.com.