2014-04-18 3 views
2

업로드 된 파일을 GridFS에 저장하려면 Play Framework 및 ReactiveMongo DB를 사용하고 있습니다. 여기 코드는 다음과 같습니다ReactiveMongo 및 GridFS를 사용하여 PlayFramework에서 업로드 된 이미지 크기 조정

def saveAttachment(id: String) = Action.async(gridFSBodyParser(gridFS)) { request => 
    // here is the future file! 
    val futureFile = request.body.files.head.ref 
    // when the upload is complete, we add the article id to the file entry (in order to find the attachments of the article) 
    val futureUpdate = for { 
     file <- futureFile 
     // here, the file is completely uploaded, so it is time to update the user 
     updateResult <- { 
     gridFS.files.update(
      BSONDocument("_id" -> file.id), 
      BSONDocument("$set" -> BSONDocument("user" -> BSONObjectID(id)), 
      "$set" -> BSONDocument("size" -> "original"))) 
     } 
    } yield updateResult 

    futureUpdate.map { 
     case _ => Ok("xx") 
    }.recover { 
     case e => InternalServerError(e.getMessage()) 
    } 
    } 

어떻게 재산 "크기"와 다른 파일을 추가 할 수 있습니다 -> "엄지 손가락"같은 업로드 된 이미지로하지만 작은 샘에 크기를 조정할? 여기에 2 가지 문제가 있습니다 :

  • 단일 업로드시 GridFS에 2 개의 파일을 저장하려면 어떻게합니까?
  • 이미지를 저장하기 전에 이미지의 크기를 조정하려면 어떻게해야합니까?

답장을 보내 주셔서 감사합니다. 그것은 좋은 방향입니다. GridFS 솔루션을 찾고있었습니다. 여기에 내가 함께 결국 무엇을 : 아주 간단합니다

def saveAttachment(id: String) = Action.async(gridFSBodyParser(gridFS)) { request => 
    // here is the future file! 
    val futureFile = request.body.files.head.ref 
    // when the upload is complete, we add the article id to the file entry (in order to find the attachments of the article) 
    val futureUpdate = for { 
     file <- futureFile 
     // here, the file is completely uploaded, so it is time to update the user 
     updateResult <- { 
     gridFS.files.update(
      BSONDocument("_id" -> file.id), 
      BSONDocument("$set" -> BSONDocument("metadata" -> 
         BSONDocument("user" -> BSONObjectID(id), 
             "size" -> "original")))) 


     val iterator = gridFS.enumerate(file).run(Iteratee.consume[Array[Byte]]()) 
     iterator.flatMap { 
      bytes => { 
      // Create resized image 
      val enumerator: Enumerator[Array[Byte]] = Enumerator.outputStream(
       out => { 
       Image(bytes).bound(120, 120).writer(Format.JPEG).withCompression(90).write(out) 
       } 
      ) 

      val data = DefaultFileToSave(
       filename = file.filename, 
       contentType = file.contentType, 
       uploadDate = Some(DateTime.now().getMillis), 
       metadata = file.metadata ++ BSONDocument(
       "user" -> BSONObjectID(id), 
       "size" -> "thumb" 
      ) 
      ) 

      Logger.warn(s"Saving resized image: [id=$id, metadata=${data.metadata}}]") 
      gridFS.save(enumerator, data).map { 
       image => Some(image) 
      } 
      } 
     } 
     } 
    } yield updateResult 

    futureUpdate.map { 
     case _ => Ok("xx") 
    }.recover { 
     case e => InternalServerError(e.getMessage()) 
    } 
    } 

답변

2

솔루션, 나는 이미지 처리를 위해 scrimage을 사용하고, 여기 내 컨트롤러 :

// imports omitted 

def upload = Authenticated.async(parse.multipartFormData) { request => 

    // some plumbing omitted 

    request.body.file("photo") match { 
    // validations omitted 
    case Some(photo) => 
     val fileToSave = DefaultFileToSave(photo.filename, photo.contentType) 
     val resizedFile = Image(photo.ref.file).fitToWidth(120).write 
     val enumerator = Enumerator(resizedFile) 
     gfs.save(enumerator, fileToSave) map { 
     case file => 
      val id = file.id.asInstanceOf[BSONObjectID].stringify 
      Ok(obj("files" -> Seq(obj(
      "id" -> id, 
      "name" -> file.filename, 
      "size" -> file.length, 
      "url" -> routes.Photos.photo(id).url, 
      "thumbnailUrl" -> routes.Photos.photo(id).url, 
      "deleteUrl" -> "", 
      "deleteType" -> "DELETE" 
     )))) 
     } recover { 
     case e => 
      Logger.error(e.toString) 
      InternalServerError("upload failed") 
     } 
    } 
    } 
} 

크기 조정 부분을 유의하시기 바랍니다가.

첫 번째 문제는 기본 파일을 복사하고 두 번째로크기 변경 복사본으로 호출하여 해결할 수 있습니다. 필자는 코드 작성에 완벽한 해결책이 없으므로 추가 도움이 필요하면 세부 사항을 요청하십시오.

관련 문제