رفع وتحميل الصور، تغيير الحجم، مخزن في قاعدة البيانات، وعرض
-
05-07-2019 - |
سؤال
هل هناك مثال مختصر لكيفية تحميل صورة، حجمه، واحفظها في قاعدة البيانات ومن ثم تخدم صورة حتى باستخدام مصعد؟
وأنا متأكد من أني يمكن أن قطعة معا من تحميل الملفات، جافا 2D API، مخطط رفع واجهات برمجة التطبيقات الاستجابة. لكن هل هناك أي رمز المثال يمكنني اتباعها لتفعل ذلك "الصحيحة" أو الطريقة الموصى بها؟
المحلول
وأنا فعلت هذا لحقل معين مرتبط S3 عن طريق إنشاء MappedField جديدة. ولدي أيضا بعض التعليمات البرمجية لتغيير، ولكن لم تختبر أو نشرها (حتى استخدام بحذر).
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)
يخزن ذلك إلى قاعدة البيانات. يمكن تعيين الحقول A new Document
باستخدام طريقة set
. محاولة اللعب مع delete_!
، find
وأساليب findAll
من المفرد Document
حذف أو العثور عليه في قاعدة البيانات. يجب أن تكون واضحة من هذه النقطة.
وأخيرا، لعرض الصور، يمكنك تجاوز قواعد إيفاد رفع ل(في الصف التمهيد، 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)
}
واستنادا إلى إجابة مقبولة من قبل جون هوفمان، أنا ثابت البق. روايته عبث تصل نسبة الارتفاع (دائما يصبح 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
}
}