2009-09-10 17 views
9

画像をアップロードし、サイズを変更し、データベースに保存し、Liftを使用して画像を提供する方法の簡潔な例がありますか?イメージをアップロード、サイズ変更、データベースに保存、表示

ファイルアップロード、Java 2D API、リフトマッパー、レスポンスAPIからまとめてもいいと思います。しかし、私が「正しい」方法や推奨する方法を実行するための例コードはありますか?

+2

嫌なことはありませんが、これはまともなプロジェクトのようです。それには陰謀、冒険、SQLなどすべてがあります。 –

+0

うん、私は行くつもりだった!私はちょうど私が始める前に助言を求めると思った。 – Joe

答えて

6

新しいMappedFieldを作成して、s3にリンクされたMapperフィールドでこれを行いました。サイズを変更するコードもありますが、テストやデプロイはしていません(注意して使用してください)。

class MappedS3Image[T<:Mapper[T]](owner: T, val path:String, maxWidth: String, maxHeight:String) extends MappedString[T](owner, 36) { 

    def url:String = MappedS3Image.fullImgPath(path, is) 

    def setFromUpload(fileHolder: Box[FileParamHolder]) = { 
     S3Sender.uploadImageToS3(path, fileHolder).map(this.set(_)) 
    } 

    override def asHtml:Node = <img src={url} style={"max-width:" + maxWidth + ";max-height:"+maxHeight} /> 
    override def _toForm: Box[Elem] = Full(SHtml.fileUpload(fu=>setFromUpload(Full(fu)))) 

} 


import java.awt.Image 
import java.awt.image.BufferedImage 
import javax.imageio.ImageIO 
import java.awt.Graphics2D 
import java.awt.AlphaComposite 

object ImageResizer { 

    def resize(is:java.io.InputStream, maxWidth:Int, maxHeight:Int):BufferedImage = { 
     val originalImage:BufferedImage = ImageIO.read(is) 

     val height = originalImage.getHeight 
     val width = originalImage.getWidth 

     if (width <= maxWidth && height <= maxHeight) 
      originalImage 
     else { 
      var scaledWidth:Int = width 
      var scaledHeight:Int = height 
      val ratio:Double = width/height 
      if (scaledWidth > maxWidth){ 
       scaledWidth = maxWidth 
       scaledHeight = (scaledWidth.doubleValue/ratio).intValue 
      } 
      if (scaledHeight > maxHeight){ 
       scaledHeight = maxHeight 
       scaledWidth = (scaledHeight.doubleValue*ratio).intValue 
      } 
      val scaledBI = new BufferedImage(scaledWidth, scaledHeight, BufferedImage.TYPE_INT_RGB) 
      val g = scaledBI.createGraphics 
      g.setComposite(AlphaComposite.Src) 
      g.drawImage(originalImage, 0, 0, scaledWidth, scaledHeight, null); 
      g.dispose 
      scaledBI 
     } 
    } 
} 
+0

欠陥のある数学。これは、幅/高さ比を混乱させる。私は固定版(3年後)で答えました。それでも、私に使ってもらうための正しいライブラリに関する質問に答えてくれてとても役に立ちました。 –

+0

私は以下の訂正された回答を追加しました。 –

3

イメージのサイズを変更し、ファイルへの参照をファイルシステムに保存する方法については、もう1つの回答で詳しく説明しています。

リフトマッパーを使用して実際のファイルの内容を保存する場合は、カスタムモデルオブジェクトを作成し、その上にバイナリフィールドを定義する必要があります。最後に、このDocumentを追加し、ブートストラップクラスで、その後

package code { 
package model { 


import _root_.net.liftweb.mapper._ 
import _root_.net.liftweb.util._ 
import _root_.net.liftweb.common._ 


// singleton object which manipulates storing of Document instances 
object Document extends Document with KeyedMetaMapper[Long, Document] { 
} 



class Document extends KeyedMapper[Long, Document] { 
    def getSingleton = Document 
    def primaryKeyField = id 

    object id extends MappedLongIndex(this) 

    object name extends MappedString(this, 20) { 
    override def displayName = "Name" 
    override def writePermission_? = true 
    } 

    object content extends MappedBinary(this) { 
    override def displayName = "Content" 
    override def writePermission_? = true 
    } 
} 



} 
} 

:このような何かを試してみてください

Schemifier.schemify(true, Schemifier.infoF _, User, Document) 

出来上がり。 Document save (new Document)を使用すると、データベースに格納されます。 setメソッドを使用して、new Documentのフィールドを設定することができます。 delete_!findfindAllシングルトンの方法を試してみてください。削除するか、データベースで見つけてください。Documentこの時点から、それは簡単であるはずです。

最後に、イメージを表示するために、Liftのディスパッチルール(ブートストラップクラスBoot.scala)をオーバーライドできます。

def getFile(filename: String): Option[Document] = { 
    val alldocs = Document.findAll() 
    alldocs.find(_.name.get == filename) 
} 

LiftRules.statelessDispatchTable.append { 
    case Req("file" :: name :: Nil, "pdf", GetRequest) => 
    () => 
    println("Got request for: " + name + ".pdf") 
    for { 
     stream <- tryo(
     getFile(name + ".pdf") map { 
      doc => new java.io.ByteArrayInputStream(doc.content.get) 
     } getOrElse null 
    ) 
     if null ne stream 
    } yield StreamingResponse(stream, 
          () => stream.close, 
           stream.available, 
           List("Content-Type" -> "application/pdf"), 
           Nil, 
           200) 
} 
2

Jon Hoffmanの回答に基づいて、私はバグを修正しました。数学的には数少ないため、アスペクト比は常に1:1になります。このバージョンは、フィットするまで大きな画像のサイズを変更し、アスペクト比を尊重します。

def resize(is:java.io.InputStream, maxWidth:Int, maxHeight:Int):BufferedImage = { 
    require (maxWidth > 0) 
    require (maxHeight > 0) 
    val originalImage:BufferedImage = ImageIO.read(is) 

    var height = originalImage.getHeight 
    var width = originalImage.getWidth 

    // Shortcut to save a pointless reprocessing in case the image is small enough already 
    if (width <= maxWidth && height <= maxHeight) 
     originalImage 
    else {   
     // If the picture was too big, it will either fit by width or height. 
     // This essentially resizes the dimensions twice, until it fits 
     if (width > maxWidth){ 
      height = (height.doubleValue() * (maxWidth.doubleValue()/width.doubleValue())).intValue 
      width = maxWidth 
     } 
     if (height > maxHeight){ 
      width = (width.doubleValue() * (maxHeight.doubleValue()/height.doubleValue())).intValue 
      height = maxHeight 
     } 
     val scaledBI = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB) 
     val g = scaledBI.createGraphics 
     g.setComposite(AlphaComposite.Src) 
     g.drawImage(originalImage, 0, 0, width, height, null); 
     g.dispose 
     scaledBI 
    } 
} 
関連する問題