문제

이미지를 업로드하고 크기를 조정하고 데이터베이스에 저장 한 다음 리프트를 사용하여 이미지를 제공하는 방법에 대한 간결한 예가 있습니까?

파일 업로드, Java 2D API, 리프트 맵퍼 및 응답 API에서 함께 조각 할 수 있다고 확신합니다. 그러나 '올바른'또는 권장 방법을 수행하기 위해 따라갈 수있는 예제 코드가 있습니까?

도움이 되었습니까?

해결책

나는 새로운 맵핑 필드를 만들어 S3에 연결된 매퍼 필드를 위해 이것을했다. 또한 크기를 조정할 코드가 있지만 테스트 또는 배포되지 않았습니다 (따라서주의해서 사용).

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
        }
    }
}

다른 팁

다른 대답은 이미지 크기를 조정하고 파일 시스템의 파일에 대한 참조를 저장하는 방법을 잘 설명합니다.

리프트 맵퍼를 사용하여 실제 파일 내용을 저장하려면 사용자 정의 모델 객체를 만들고 이진 필드를 정의해야합니다. 다음과 같은 것을 시도하십시오.

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
  }
}



}
}

그런 다음 부트 스트랩 클래스에서 이것을 추가하십시오 Document 결국 :

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

진성. 사용 Document save (new Document) 데이터베이스에 저장합니다. ㅏ new Document의 필드를 사용하여 설정할 수 있습니다 set 방법. 함께 놀아보세요 delete_!, find, findAll 방법의 방법 Document 싱글 톤으로 데이터베이스에서 삭제하거나 찾을 수 있습니다. 이 시점에서 간단해야합니다.

마지막으로 이미지를 표시하려면 Lift의 디스패치 규칙 (부트 스트랩 클래스, boot.scala)을 무시할 수 있습니다. PDF 요청에 대한 규칙을 무시하는이 예제를 사용해보십시오.

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)
}

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
    }
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top