Heben Sie das Hochladen von Bildern, Größe ändern, speichern in Datenbank, Anzeige
-
05-07-2019 - |
Frage
Gibt es ein prägnantes Beispiel dafür, wie ein Bild hochladen, Größe ändern, sollte sie in einer Datenbank und dann das Bild dient Aushebung mit?
Ich bin sicher, dass ich es zusammen aus der Datei-Upload-piece könnte, Java 2D-API, Lift Mapper und Response-APIs. Aber gibt es einen Beispielcode ich folgen kann, es zu tun, um den ‚richtigen‘ oder empfohlene Weg?
Lösung
Ich tat dies für ein Mapper Feld durch die Schaffung eines neuen MappedField bis s3 verbunden. Ich habe auch einen etwas Code, um die Größe, aber noch nicht getestet oder eingesetzt (so mit Vorsicht verwenden).
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
}
}
}
Andere Tipps
Die andere Antwort beschreibt schön, wie die Größe des Bildes und einen Verweis auf die Datei auf dem Dateisystem gespeichert werden.
Wenn Sie den Lift-Mapper zum Speichern der tatsächlichen Dateiinhalte verwenden möchten, müssen Sie Ihr eigenes Model-Objekt erstellen, und definieren auf sie ein binäres Feld. Probieren Sie etwas wie folgt aus:
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
}
}
}
}
Dann in Bootstrap-Klasse, fügen Sie diese Document
am Ende:
Schemifier.schemify(true, Schemifier.infoF _, User, Document)
Voila. Mit Document save (new Document)
speichert sie in der Datenbank. Ein Feld des new Document
kann mit dem set
Verfahren eingestellt werden. Versuchen Sie, mit delete_!
spielen, find
, findAll
Methoden des Document
Singleton zu löschen oder in der Datenbank zu finden. Es soll von diesem Punkt an unkompliziert sein.
Schließlich das Bild anzuzeigen, können Sie Lift Zuteilungsregeln (in Bootstrap-Klasse, Boot.scala) außer Kraft setzen. Versuchen Sie, mit diesem Beispiel spielen um die die Regeln für pdf-Anfragen hat Vorrang vor:
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)
}
Auf der Grundlage der akzeptierten Antwort von Jon Hoffman, befestigte ich die Bugs. Seine Version verunstaltet das Seitenverhältnis (es immer wird 1: 1), weil die Mathematik war weg in ein paar Flecken. Diese Version passt die Größe große Bilder, bis sie passen, und achtet das Seitenverhältnis.
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
}
}