如何使用Akka HTTP构造调用Facebook API的form-data请求?
用Akka HTTP实现Facebook视频分片上传的Form-Data请求
嘿,我来帮你搞定这个需求!先对照你给出的curl示例和FBSingleChunkUpload case class,一步步实现对应的form-data POST请求:
第一步:补全你的Case Class
首先把case class的字段和curl里的参数一一对应上,确保所有必要字段都包含:
case class FBSingleChunkUpload( accessToken: String, // 对应curl里的access_token sessionId: String, // 对应upload_session_id startOffset: Long, // 对应start_offset videoChunk: java.io.File // 对应video_file_chunk的本地文件,也可以换成流式Source )
第二步:构建Akka HTTP的Form-Data实体
Akka HTTP通过Multipart.FormData来处理form-data类型的请求,我们需要把每个字段转换成对应的BodyPart:
先导入必要的包
确保你的项目依赖里已经包含Akka HTTP,然后导入这些核心包:
import akka.actor.ActorSystem import akka.http.scaladsl.Http import akka.http.scaladsl.model._ import akka.stream.scaladsl.FileIO import scala.concurrent.Future
编写FormData构建函数
把case class的内容转换成符合要求的form-data结构:
def buildFormData(uploadReq: FBSingleChunkUpload): Multipart.FormData = { // 普通文本字段部分 val accessTokenPart = Multipart.FormData.BodyPart( "access_token", HttpEntity(ContentTypes.`text/plain(UTF-8)`, uploadReq.accessToken) ) // upload_phase是固定值transfer val uploadPhasePart = Multipart.FormData.BodyPart( "upload_phase", HttpEntity(ContentTypes.`text/plain(UTF-8)`, "transfer") ) val startOffsetPart = Multipart.FormData.BodyPart( "start_offset", HttpEntity(ContentTypes.`text/plain(UTF-8)`, uploadReq.startOffset.toString) ) val sessionIdPart = Multipart.FormData.BodyPart( "upload_session_id", HttpEntity(ContentTypes.`text/plain(UTF-8)`, uploadReq.sessionId) ) // 文件块部分:用FileIO读取本地文件,自动处理流式上传 val videoChunkPart = Multipart.FormData.BodyPart.fromFile( "video_file_chunk", ContentType(MediaTypes.`video/mp4`), uploadReq.videoChunk ) // 把所有BodyPart组合成完整的FormData Multipart.FormData(accessTokenPart, uploadPhasePart, startOffsetPart, sessionIdPart, videoChunkPart) }
第三步:发送POST请求并处理响应
编写发送请求的函数,处理Akka HTTP的异步响应:
def sendFacebookUploadRequest(uploadReq: FBSingleChunkUpload)(implicit system: ActorSystem): Future[HttpResponse] = { import system.dispatcher val formData = buildFormData(uploadReq) // 替换成你实际的Facebook API端点 val apiUri = Uri("https://graph-video.facebook.com/v2.3/1533641336884006/videos") val httpRequest = HttpRequest( method = HttpMethods.POST, uri = apiUri, entity = formData.toEntity(HttpCharsets.`UTF-8`) ) // 发送单次请求 Http().singleRequest(httpRequest) }
使用示例
这里是一个简单的调用示例,上传本地的chunk文件:
// 初始化ActorSystem(Akka HTTP的核心依赖) implicit val system: ActorSystem = ActorSystem("FacebookVideoUploader") val chunkFile = new java.io.File("chunk1.mp4") val uploadRequest = FBSingleChunkUpload( accessToken = "XXXXXXX", sessionId = "1564747013773438", startOffset = 0, videoChunk = chunkFile ) // 发送请求并处理结果 sendFacebookUploadRequest(uploadRequest).onComplete { case scala.util.Success(response) => println(s"上传请求响应状态: ${response.status}") // 可以进一步读取响应体内容 response.entity.dataBytes.runForeach(bs => println(bs.utf8String)) case scala.util.Failure(ex) => println(s"上传失败,错误信息: ${ex.getMessage}") }
额外注意事项
- 如果你的视频块不是本地文件,而是流式数据(比如从网络读取的字节流),可以用自定义的
Source[ByteString, _]来构建文件BodyPart:val chunkSource: akka.stream.scaladsl.Source[ByteString, _] = // 你的流式数据源 val videoChunkPart = Multipart.FormData.BodyPart( "video_file_chunk", HttpEntity(ContentType(MediaTypes.`video/mp4`), chunkSource), Map("filename" -> "chunk1.mp4") // 记得指定文件名 ) - 生产环境中不要用
Await等待Future结果,建议用回调或者for-comprehension处理异步流程 - 你用的Facebook API v2.3版本比较老旧,建议尽量升级到较新的版本以获得更好的兼容性和功能
内容的提问来源于stack exchange,提问作者Alex Fruzenshtein
相关产品推荐
相关产品推荐

