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

Download media file from twilio, using the media URI

我在下载彩信中提供的 media from the media uri 时遇到了问题。

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

1st url -> 2nd url -> above url ;so,all in all 2 redirects

如果我用新的 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)
    }
  }

这是我到目前为止一直使用的方法(有效),如播放文档中所述。但是我需要一个同步方法,这意味着我需要执行另一个步骤 成功下载文件 .抱歉,没有提前说清楚。

更新 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 客户端跟随重定向应该非常简单,使用 documented option 到客户端:

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 及更低版本; the bodyAsBytes method of WSResponse returns an Array[Byte]. If you're on the current cutting-edge and using Play 2.5.x, bodyAsBytes gives you an Akka ByteString 有很多不错的功能方法,但如果您只想存储数据,您可能只想调用 toArray

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