【问题标题】:Play Framework - build a TemporaryFile from a file stored in RAMPlay Framework - 从存储在 RAM 中的文件构建 TemporaryFile
【发布时间】:2022-01-31 21:14:30
【问题描述】:

我正在使用 Scala Play Framework 以多部分表单数据的形式向客户端发送图像,作为对获取请求的响应。

我以BufferedImage 格式存储图像。目前,我使用getResult 方法将图像发送回客户端:

@Singleton
class ResultController @Inject()(val controllerComponents: ControllerComponents) extends BaseController with DefaultWriteables{

    class ResultForm(seq: Seq[BufferedImage]){
        val (leftRotation, rightRotation, backRotation) = seq.zip(
            Seq("left", "right", "back")
        ).map{ case (bufferedImage: BufferedImage, partName: String) =>
            val bos = new ByteArrayOutputStream()
            ImageIO.write(bufferedImage, "png", bos)
            MultipartFormData.FilePart(
                partName,
                s"${partName}_result.png",
                Some("image/png"),
                ByteString.fromArray(bos.toByteArray())
            ) 
        } match {
            case Seq(l, r, b) => (l, r, b)
        }

        def getResponse() = {
            MultipartFormData(
                dataParts = Map[String, Seq[String]](), 
                files = Seq(leftRotation, rightRotation, backRotation),
                badParts =Seq()
            )
        }
    }

    implicit def writeableOf_MultipartFormDataWithBs(
        codec: Codec,
        contentType: Option[String]
    ):play.api.http.Writeable[MultipartFormData[akka.util.ByteString]] = {
        writeableOf_MultipartFormData(
            codec,
            Writeable[MultipartFormData.FilePart[akka.util.ByteString]](
                (bs: MultipartFormData.FilePart[akka.util.ByteString]) => bs.ref,
                contentType
            )
        )
    }


    def getResult(accessKey: String) = Action{request => 
        val jobResult = GeneratorData.getJobResult(accessKey)


        jobResult match {
            case Some(files) => {
                val rf = new ResultForm(files)
                Ok(
                    rf.getResponse()
                )(
                    writeableOf_MultipartFormDataWithBs(
                        Codec.iso_8859_1,
                        contentType = Some("multipart/form-data")
                    )
                )
            }
            case None => BadRequest(Json.toJson(
                new ErrorResponse("The result was not found on the server")
            ))
        }
    }    
}

但是,在客户端 javascript 中,Response.formData() 仅适用于 chrome 和 opera,但 firefox 会抛出 TypeError: Could not parse content as FormData. 异常。这可能是由于正在进行的图像格式的一些疯狂转换,以及自定义编写器的定义。

如果不是 akka ByteString 我只是传递了一个 TemporaryFile ,那么整个事情会容易得多, documentation 没有列出任何像“create”这样的方法。 有一个 TemporaryFileCreator 特征,但它的子类似乎都没有从任何类型的内存文件转换为 TemporaryFile 的方法。但是,它们确实有指定文件路径的方法,但我只需要使用 RAM 来提供文件。

那么,有没有办法从内存中的文件数据创建一个 TemporaryFile?或者也许是一种将三个图像作为多部分发送的方法,以便 Firefox,而不仅仅是 Opera 和 chromium 可以解析结果? Base64 也是一种解决方案,但我更愿意以“正确”的方式做到这一点。

【问题讨论】:

    标签: javascript scala firefox playframework multipartform-data


    【解决方案1】:

    所以我在 python 中实现了一个简单的示例,结果证明这是一个 Firefox 错误。您可以在此处跟踪错误报告: https://bugzilla.mozilla.org/show_bug.cgi?id=1752761

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-09-25
      • 1970-01-01
      • 2016-08-18
      • 2017-05-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-11
      相关资源
      最近更新 更多