存储(二进制)文件 - 在 Heroku 中使用 Scala 播放框架



我正在尝试将用户上传的图像存储在由 scala 和 play framework 2.2.x 编写的应用程序中我已经在 heroku 中部署了我的应用程序。Heroku不允许我将文件保存在文件系统中。所以我试图将我的文件存储在数据库中。

这是我用于存储图像的代码:

def updateImage(id: Long, image: Array[Byte]) = {
val selected = getById(id)
DB.withConnection {
  implicit c =>
    SQL("update subcategory set image={image} where id = {id}").on('id -> id, 'image -> image).executeUpdate()
}
selected }

这是我用来检索图像的代码:

  def getImageById(id: Long): Array[Byte] = DB.withConnection {
  implicit c =>
  val all = SQL("select image from subcategory where id = {id}").on('id -> id)().map {
    case Row(image: Array[Byte]) => image
    case Row(Some(image: Array[Byte])) => image
    case Row(image: java.sql.Blob )=> image.getBytes(0 , image.length().toInt)
  }
  all.head
 }

问题是:当我使用 H2 数据库和 blob 列时,我收到"匹配错误"异常。当我使用 Postgresql 和 bytea 列时,我没有收到任何错误,但是当我检索图像时,它是十六进制格式,数组开头的一些字节丢失了。

根据 PostgreSQL 文档,bytea数组的长度存储在数组开头的四个字节中。当您读取该行时,它们会被剥离,因此当您将 Scala 中的数据与数据库中的数据进行比较时,它们似乎"丢失"了。

如果您希望 Web 浏览器正确显示图像,则必须将响应的内容类型设置为适当的值,否则它不知道它正在接收图像数据。Ok.sendFile助手会为您完成此操作。否则,您将不得不手动完成:

  def getPicture = Action {
      SimpleResult(
          header = ResponseHeader(200),
          body = Enumerator(pictureByteArray))
      .as(pictureContentType)
  }

在上面的示例中,pictureByteArray 是包含数据库中的图片数据的Array[Byte]pictureContentType是具有相应内容类型(例如 image/jpeg)的字符串。

这在 Play 文档中得到了很好的解释。

最新更新