RequestBodyHandler中捕获异常

时间:2014-06-27 10:47:21

标签: scala amazon-s3 netty nio

下面是用户将视频从移动应用程序上传到S3时的代码

def uploadVideo = Action(parse.multipartFormData) { implicit request =>
      try {
        var height = 0
        var width = 0
        request.body.files.map { mov =>
          var videoName = System.currentTimeMillis() + ".mpeg"
          amazonS3Client.putObject(bucketVideos, videoName, mov.ref.file)
        }
        val map = Map("result" -> "success")
        Ok(write(map))
      } catch {
        case e: Exception =>
          Ok(write(Map("result" -> "error")))
      }
  }

上面的代码工作正常但是如果用户在上传视频时取消则会发生错误

    [error] play - Exception caught in RequestBodyHandler
java.nio.channels.ClosedChannelException: null
    at org.jboss.netty.channel.socket.nio.AbstractNioWorker.cleanUpWriteBuffer(AbstractNioWorker.java:434) ~[netty.jar:na]
    at org.jboss.netty.channel.socket.nio.AbstractNioWorker.writeFromUserCode(AbstractNioWorker.java:129) ~[netty.jar:na]
    at org.jboss.netty.channel.socket.nio.NioServerSocketPipelineSink.handleAcceptedSocket(NioServerSocketPipelineSink.java:99) ~[netty.jar:na]
    at org.jboss.netty.channel.socket.nio.NioServerSocketPipelineSink.eventSunk(NioServerSocketPipelineSink.java:36) ~[netty.jar:na]
    at org.jboss.netty.channel.Channels.write(Channels.java:725) ~[netty.jar:na]
    at org.jboss.netty.handler.codec.oneone.OneToOneEncoder.doEncode(OneToOneEncoder.java:71) ~[netty.jar:na]

这不会阻挡!!

  

1.这对服务器是否有害?(因为如果出现错误则不需要任何响应)

     

2.如果是,如何处理?

1 个答案:

答案 0 :(得分:3)

这一切都发生在Play的内部,正在处理解析Request的正文。实际上,在上传到服务器期间,您还没有到达 try块,因为该文件尚未完成上传。只有在上传完成后,您才能使用TemporaryFile

所以不,你不能抓住这个错误,为什么你想要?用户关闭了连接。他们甚至没有等待回复,为什么要送一个呢?让Play处理它。

但这也不是处理上传的好方法。对于小文件,它是可以通过的,但如果有人通过您的服务器代理一个巨大的视频上传到S3,它将会:

  1. 花费差不多两倍的时间来响应(这会导致用户在您上传到S3时挂起)。
  2. 阻止一个Play的线程,用于处理文件上传到S3的整个时间的请求,并且给予足够的上传次数(根本不是很多),您将无法再处理请求,直到上传完成。
  3. 至少考虑创建一个单独的ExecutionContext用于处理上传,或者甚至更好地考虑让用户通过签名表单直接上传到S3,这样就无需代理上传。