2009-09-10 31 views
9

Có một ví dụ ngắn gọn về cách tải lên hình ảnh, thay đổi kích thước, lưu trữ hình ảnh trong cơ sở dữ liệu và sau đó phân phối hình ảnh bằng Lift?Tải lên hình ảnh thang máy, thay đổi kích thước, lưu trữ trong cơ sở dữ liệu, hiển thị

Tôi chắc chắn rằng tôi có thể ghép nó lại với nhau từ tệp tải lên, API Java 2D, API Trình tải lên và phản hồi. Nhưng có bất kỳ mã ví dụ nào tôi có thể làm theo để làm theo cách 'đúng' hoặc được đề nghị không?

+2

Không có hành vi phạm tội, nhưng điều này nghe có vẻ giống như một dự án tốt để tự viết! Nó có mọi thứ: âm mưu, phiêu lưu và SQL. –

+0

Vâng, tôi sẽ đến! Tôi chỉ nghĩ rằng tôi sẽ tìm kiếm lời khuyên trước khi bắt đầu. – Joe

Trả lời

6

Tôi đã làm điều này cho trường Mapper được liên kết với s3 bằng cách tạo MappedField mới. Tôi cũng có một số mã để thay đổi kích thước, nhưng chưa được kiểm tra hoặc triển khai (vì vậy hãy sử dụng cẩn thận).

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

Toán học thiếu sót. Điều này làm rối loạn tỷ lệ chiều rộng/chiều cao. Tôi đã trả lời với một phiên bản cố định (ba năm sau). Tuy nhiên, nó đã trả lời các câu hỏi về các thư viện chính xác để sử dụng cho tôi và rất hữu ích. –

+0

Tôi đã thêm câu trả lời đúng vào bên dưới. –

3

Câu trả lời khác mô tả cách thay đổi kích thước hình ảnh và lưu trữ tham chiếu đến tệp trên hệ thống tệp.

Nếu bạn muốn sử dụng trình vẽ bản đồ để lưu trữ nội dung tệp thực, bạn phải tạo đối tượng mô hình tùy chỉnh và xác định trường nhị phân trên đó. Hãy thử một cái gì đó như thế này:

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



} 
} 

Sau đó, trong lớp bootstrap, thêm Document này ở cuối:

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

Voila. Sử dụng Document save (new Document) lưu nó vào cơ sở dữ liệu. Bạn có thể đặt các trường của new Document bằng cách sử dụng phương thức set. Thử chơi với các phương thức delete_!, find, findAll của Document singleton để xóa hoặc tìm nó trong cơ sở dữ liệu. Nó nên được đơn giản từ thời điểm này trên.

Cuối cùng, để hiển thị hình ảnh, bạn có thể ghi đè lên các quy tắc điều phối của Lift (trong lớp bootstrap, Boot.scala). Hãy thử phát xung quanh với ví dụ này ghi đè các quy tắc cho yêu cầu 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) 
} 
2

Dựa trên câu trả lời được chấp nhận bởi Jon Hoffman, tôi đã sửa lỗi. Phiên bản của anh ta làm lộn xộn tỉ lệ khung hình (nó luôn luôn trở thành 1: 1), bởi vì toán học đã bị tắt ở một vài điểm. Phiên bản này thay đổi kích thước hình ảnh lớn cho đến khi chúng vừa với nhau và tôn trọng tỷ lệ cỡ ảnh.

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 
    } 
} 
Các vấn đề liên quan