当前位置: 首页 > 知识库问答 >
问题:

Play Framework 2.8的alpakka s3文件下载问题

葛雪松
2023-03-14

在S3服务中:

def download(link: String): Source[Option[(Source[ByteString, NotUsed], ObjectMetadata)], NotUsed] = {
    S3.download(TraktrainBucket.DOWNLOAD_BUCKET, link)
}

在控制器中:

          val source = s3Service.download(link).map(s => s.map(_._1))
          val trackName = "track name"
          val filename = trackName.replaceAll("[^A-Za-z0-9 \\-.]", "") + (if (track.drumKit) ".zip" else ".mp3")
          val disposition = "attachment; filename=\"" + filename + "\""
          Result(
            header = ResponseHeader(200, Map("Content-Disposition" -> disposition)),
            body = HttpEntity.Streamed(source.flatMapConcat(_.getOrElse(Source.empty)), None, Some("application/octet-stream"))
          )

另外,我还有一个上传程序(它需要一个mp3文件,用ffmpeg处理它,然后将它上传到s3,就像这样:

def richUploadMp3(extension: String, checkFunction: (String, Option[String]) => Boolean, cannedAcl: CannedAcl, bucket: String) = producerAction(parse.multipartFormData(handleFilePartAsFile)).async { implicit request =>
    val s3Filename = request.user.get.id + "/" + java.util.UUID.randomUUID.toString + "." + extension
    val s3FilenameTagged = request.user.get.id + "/" + java.util.UUID.randomUUID.toString + "." + extension
    val fileOption = request.body.file("file").map {
      case FilePart(key, filename, contentType, file, _, _) =>
        logger.info(s"key = ${key}, filename = ${filename}, contentType = ${contentType}, file = $file")
        if(checkFunction(filename, contentType)) {
          val taggedFile = audioService.putTag(file)
          for {
            mp3 <- FileIO.fromPath(file.toPath).runWith(s3Service.uploadSink(s3Filename, cannedAcl, TraktrainBucket.DOWNLOAD_BUCKET))
            mp3Tagged <- FileIO.fromPath(taggedFile.toPath).runWith(s3Service.uploadSink(s3FilenameTagged, cannedAcl, TraktrainBucket.STREAMING_BUCKET))
          } yield (mp3, mp3Tagged, file, taggedFile)
        } else {
          throw new Exception("Upload failed")
        }
    }
    fileOption match {
      case Some(opt) => opt.map(o => {
        o._3.delete()
        o._4.delete()
        Ok(Json.toJson(Seq(s3Filename, s3FilenameTagged)))
      })
      case _ => Future.successful(BadRequest("ERROR"))
    }
  }
exceeded configured max-open-requests value of 1024
akka {
  loglevel = DEBUG

  http {
    client {
      connecting-timeout = 5 s
      idle-timeout = 5 s
      parsing {
        max-content-length = 3000m
      }
    }
    server {
      parsing {
        max-content-length = 3000m
      }
    }

    host-connection-pool {
      max-open-requests = 1024
      idle-timeout = 10 s
      client {
        connecting-timeout = 10 s
        idle-timeout = 10 s
      }
    }
  }
}
Response stream for [GET /free/642241] failed with 'TCP idle-timeout encountered on connection to [s3.us-west-2.amazonaws.com:443], no bytes passed in the last 10 seconds'. Aborting connection.
val AkkaVersion = "2.5.31"
val AkkaHttpVersion = "10.1.12"
libraryDependencies ++= Seq(
  "com.lightbend.akka" %% "akka-stream-alpakka-s3" % "2.0.1",
  "com.typesafe.akka" %% "akka-stream" % AkkaVersion,
  "com.typesafe.akka" %% "akka-http" % AkkaHttpVersion,
  "com.typesafe.akka" %% "akka-http-xml" % AkkaHttpVersion
)

共有1个答案

伯和蔼
2023-03-14

检查为后端Akka HTTP服务器制作的播放设置中的设置。如果RequestTimeout设置为Infinite,这是默认值,请将其更改为应用程序的合理时间限制。这可能会在连接中出现故障时导致连接长时间运行。如下文所述,这些配置覆盖了Akka配置。

https://www.playframework.com/documentation/2.8.x/settingsakkahttp

注意:Akka HTTP有许多超时配置,您可以使用这些配置来保护应用程序免受攻击或编程错误。正在运行的Akka HTTP服务器将自动识别所有这些Akka配置。例如,如果您有如下的idle-timeout和request-timeout配置:akka.http.server.idle-timeout=20sakka.http.server.request-timeout=30s它们将被自动识别。请记住,上面列出的播放配置将覆盖Akka的配置

    null

为什么这种情况只发生在Akka Http上而不发生在[插入其他客户端]上

默认情况下,许多Java HTTP客户端不会对所使用的某些资源设置限制。例如。有些客户端永远不会将请求排队,而只是在所有池连接当前都忙的情况下打开到服务器的另一个连接。然而,这可能只是将问题从客户端转移到服务器端。此外,使用过多的连接会导致网络性能下降,因为更多的连接会争夺带宽。

还要查看Akka HTTP的S3示例页面

# Defines the default time period within which the application has to
# produce an HttpResponse for any given HttpRequest it received.
# The timeout begins to run when the *end* of the request has been
# received, so even potentially long uploads can have a short timeout.
# Set to `infinite` to completely disable request timeout checking.
#
# Make sure this timeout is smaller than the idle-timeout, otherwise,
# the idle-timeout will kick in first and reset the TCP connection
# without a response.
#
# If this setting is not `infinite` the HTTP server layer attaches a
# `Timeout-Access` header to the request, which enables programmatic
# customization of the timeout period and timeout response for each
# request individually.
request-timeout = 20 s
 类似资料:
  • 在edge中,我正在访问一个JSP页面,该页面会返回一个文件。它在chrome中工作得很好,但在Edge和Internetexplorer中,我会将mime类型附加到文件名中。 这是响应标头: Edge要求我保存文件,文件名是 persistenceIDs.xlsx.vnd.openxmlformats-officedocument.spreadsheetml.sheet 有什么想法吗?

  • 问题内容: 我正在应用程序中下载动态文件,并使用iframe来模拟ajax。我正在做的是,当下载请求发出后,我将创建一个动态的不可见iframe,并将iframe的src设置为下载网址。我能够成功下载该文件,但要求是显示一个下载下载指示器一旦开始下载,并在下载对话框出现后立即完成。我在创建iframe后提供了回调,以显示下载指示器已成功运行,并在iframe的“ onload”上提供了另一种方法,

  • 视频文件下载问题? 为什么在微信电脑端视频能播放还能下载,在手机上就不能下载? 同一个视频。

  • 问题内容: 我在从互联网下载我的应用程序中的二进制文件时遇到问题。在Quicktime中,如果我直接下载它,则可以正常工作,但是通过我的应用程序,它会以某种方式混乱(即使它们在文本编辑器中看起来完全一样)。这是一个例子: 问题答案: 我不知道这是否是唯一的问题,但是你在其中遇到了典型的Java故障:你没有指望总是允许read()返回的字节数少于你要求的字节数。因此,你的读取可能会少于1024个字节

  • 下载 <?php /** * 下载文件请求示例 */ require dirname(__DIR__) . '/vendor/autoload.php'; use Yurun\Util\HttpRequest; use Yurun\Util\YurunHttp; use Yurun\Util\YurunHttp\Handler\Swoole; $url = 'http://www.baid

  • 需要通过应用程序从web服务器下载文件,但该文件没有加载,下面是我使用的代码: 在清单中,我有以下权限: