Skip to content

Instantly share code, notes, and snippets.

@fmpwizard
Created December 29, 2012 22:47
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save fmpwizard/a6715d1e3664f73cd03a to your computer and use it in GitHub Desktop.
Save fmpwizard/a6715d1e3664f73cd03a to your computer and use it in GitHub Desktop.
import net.liftweb.http.rest.RestHelper
import net.liftweb.util.Helpers.AsLong
import net.liftweb.json._
import net.liftweb.json.JsonDSL._
import net.liftweb.common._
import net.liftweb.http._
import com.fmpwizard.weyesowl.code.model.{Inventory, InventoryImages}
import net.liftweb.http.OkResponse
import net.liftweb.http.InMemoryResponse
object FileUpload extends RestHelper with Loggable with FileUploadHelper {
serve {
case "upload" :: "image" :: AsLong(id) :: Nil Post AllowedMimeTypes(req) => saveAndRespond(req, id)
case "upload" :: "bypart" :: partNumber :: Nil Post AllowedMimeTypes(req) => saveAndRespond(req, partNumber)
case "upload" :: "image" :: AsLong(itemId) :: Nil Get req => listImagesForItem(req, itemId)
}
serve {
case "serving" :: "image" :: AsLong(id) :: Nil Get req => serveImageById(req, id)
case "serving" :: "image" :: AsLong(id) :: Nil Delete req => deleteImage(req, id)
}
}
trait FileUploadHelper extends Loggable {
def saveFile(fp: FileParamHolder, id: Long): List[JValue] = {
val image = InventoryImages.create
fp.file match {
case null =>
logger.debug("null")
genJsonBadResponse
case x if x.length == 0 =>
logger.debug("Size 0")
genJsonBadResponse
case x => {
logger.debug("Adding image to db")
val img = image.inventoryId(id).imgBlob(fp.file).imgMimeType(fp.mimeType).saveMe()
genJsonData(img)
}
}
}
def genJsonData(img: InventoryImages): List[JValue] = {
List(
("name" -> img.id.is)
~ ("type" -> img.imgMimeType.is)
~ ("size" -> img.imgBlob.is.length)
~ ("url" -> ("/serving/image/" + img.id.is))
~ ("thumbnail_url" -> ("/serving/image/" + img.id.is))
~ ("delete_url" -> ("/serving/image/" + img.id.is))
~ ("delete_type" -> "DELETE")
)
}
def genJsonBadResponse: List[JValue] = {
List(
("name" -> "n/a")
~ ("type" -> "n/a")
~ ("size" -> 0L)
)
}
def saveAndRespond(req: Req, id: Long): LiftResponse = {
val jvalue: List[JValue] = req.uploadedFiles.flatMap(fph => saveFile(fph, id))
JsonResponse(jvalue, ("Content-Length", jvalue.toString.getBytes.length.toString) :: ("Content-Type", "text/plain") :: Nil, Nil, 200)
}
/**
* For mass upload based on part number
*/
def saveAndRespond(req: Req, partNumber: String): LiftResponse = {
val itemId = Inventory.getItemId(partNumber)
println("here " + itemId)
val jvalue: List[JValue] = req.uploadedFiles.flatMap(fph => saveFile(fph, itemId.openOr(0L)))
JsonResponse(jvalue, ("Content-Length", jvalue.toString.getBytes.length.toString) :: ("Content-Type", "text/plain") :: Nil, Nil, 200)
}
def listImagesForItem(req: Req, itemId: Long): LiftResponse = {
logger.debug("getting file %s" format itemId)
val rows = InventoryImages.imagesByItemId(itemId)
val jvalue: JValue = rows.flatMap{ genJsonData }
JsonResponse(jvalue, ("Content-Length", jvalue.toString.getBytes.length.toString) :: ("Content-Type", "text/plain") :: Nil, Nil, 200 )
}
def serveImageById(req: Req, id: Long): LiftResponse = {
logger.debug("Calling file : %s" format id)
val row = InventoryImages.imageById(id)
val image = row.map(_.imgBlob.is).openOr("a".getBytes)
val mime = row.map(_.imgMimeType.is).openOr("image/png")
InMemoryResponse(image, ("Content-Length", image.length.toString) :: ("Content-Type", mime) :: Nil, Nil, 200)
}
def deleteImage(req: Req, id: Long) : LiftResponse = {
logger.debug("Deleted the file %s" format id)
InventoryImages.unsafeDeleteById(id)
new OkResponse
}
}
object AllowedMimeTypes extends Loggable {
def unapply(req: Req): Option[Req] = {
logger.info("req.uploadedFiles.map{_.mimeType) is %s".format(req.uploadedFiles.map{_.mimeType}))
req.uploadedFiles.flatMap{_.mimeType match {
case "image/bmp" => Some(req)
case "image/x-windows-bmp" => Some(req)
case "image/vnd.dwg" => Some(req)
case "image/gif" => Some(req)
case "image/x-icon" => Some(req)
case "image/jpeg" => Some(req)
case "image/pict" => Some(req)
case "image/png" => Some(req)
case "image/x-quicktime" => Some(req)
case "image/tiff" => Some(req)
case "image/x-tiff" => Some(req)
case _ => None
}}.headOption
}
}
@Banzaci
Copy link

Banzaci commented Feb 5, 2013

Hi.
Is it possible to have a look at the InventoryImages and Inventory?
Thanks

@awkay
Copy link

awkay commented Jul 13, 2013

Hi,

Using Lift 2.5, the content length comes out wrong in this code. I was having failures where the POST never ended...turns out this code was sending a content type of 260 when the response was really 190 bytes long. I personally removed the Content-Length header, and that fixed it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment