RoyKings 2015-10-31
PlayframeworkandFileUploadinRESTful
FileUploadinRESTfulAPIrightnow,thereareonly3optionstillnow.
1.Base64encodethefile,attheexpenseofincreasingthedatasizebyaround33%.
2.Sendthefilefirstinamultipart/form-dataPOST,andreturnandIDtotheclient.TheclientthensendsthemetadatawiththeID.Theserverre-associatesthefileandthemetadata.
3.Sendthemetadatafirst,andreturnanIDtotheclient.TheclientthensendsthefilewiththeID,andtheserverre-associatesthefileandthemetadata.
Imaychoose#2or#3.LookingatplayframeworkUploadingFilesChapter.
1.PlayframeworkFileUpload
Iwilluse“multipart/form-data”encodingtomaketheformsupportmixstandardformdatawithfileattachmentdata.
LoggingLevel
ch.qos.logback.classic.LevelTRACE,DEBUG,INFO,WARNandERROR
https://www.playframework.com/documentation/2.4.3/SettingsLogger
https://www.playframework.com/documentation/2.4.3/ScalaLogging
defupload=Action(parse.multipartFormData){request=>
request.body.file("file").map{file=>
importjava.io.File
valfilename=file.filename
valcontentType=file.contentType
Ok("Resumethere.")
}.getOrElse{
BadRequest(Json.obj("status"->"OK","message"->"Nofilesintheattachment."))
}
}
IwasoriginallythinkingthatImayseparateitinto2steps.1-uploadingfile,2-parsefile.Butafterthinkaboutthisagain.Imaychangethatto1singlestep.
2.DirectlyUploadtheFileandOtherParams
routeconfigurationtouploadthefilecontent
#ResumeRoutes
POST/api/v1/resume/parseFilecontrollers.ResumeController.parseFile()
POST/api/v1/resume/parseContentcontrollers.ResumeController.parseContent()
Theloggingconfiguration
<configuration>
<conversionRuleconversionWord="coloredLevel"converterclass="play.api.Logger$ColoredLevel"/>
<appendername="FILE"class="ch.qos.logback.core.FileAppender">
<file>logs/application.log</file>
<encoder>
<pattern>%date[%level]from%loggerin%thread-%message%n%xException</pattern>
</encoder>
</appender>
<appendername="STDOUT"class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%coloredLevel%logger{15}-%message%n%xException{10}</pattern>
</encoder>
</appender>
<appendername="ASYNCFILE"class="ch.qos.logback.classic.AsyncAppender">
<appender-refref="FILE"/>
</appender>
<appendername="ASYNCSTDOUT"class="ch.qos.logback.classic.AsyncAppender">
<appender-refref="STDOUT"/>
</appender>
<loggername="play"level="INFO"/>
<loggername="application"level="DEBUG"/>
<!--Offtheseonesastheyareannoying,andanywaywemanageconfigurationourself-->
<loggername="com.avaje.ebean.config.PropertyMapLoader"level="OFF"/>
<loggername="com.avaje.ebeaninternal.server.core.XmlConfigLoader"level="OFF"/>
<loggername="com.avaje.ebeaninternal.server.lib.BackgroundThread"level="OFF"/>
<loggername="com.gargoylesoftware.htmlunit.javascript"level="OFF"/>
<loggername="controllers.ResumeController"level="DEBUG"/>
<rootlevel="WARN">
<appender-refref="ASYNCFILE"/>
<appender-refref="ASYNCSTDOUT"/>
</root>
</configuration>
ImplementationClasstoDealwithFile
importjava.io.FileInputStream
importcom.wordnik.swagger.annotations._
importutils.IncludeLogger
importplay.api.libs.json.{JsError,Json}
importplay.api.mvc.{BodyParsers,Action,Controller}
…snip...
implicitvalresumeWrites=Json.writes[Resume]
implicitvalresumeReads=Json.reads[Resume]
@ApiOperation(value="parseFile",
notes="ParsetheResumeFile",
response=classOf[Resume],
httpMethod="POST",
produces="json",
position=1)
@ApiImplicitParams(Array(
newApiImplicitParam(
name="body",
value="ResumeFile",
required=true,
dataType="file",
paramType="body")))
@ApiResponses(Array(newApiResponse(code=200,message="SuccessfulParseResume.",response=classOf[Resume])))
defparseFile=Action(parse.multipartFormData){request=>
logger.debug("Therequestishere.")
valresume=request.body.files.map{file=>
valfilename=file.filename
logger.debug("file:"+filename+""+file.contentType)
valinputStream=newFileInputStream(file.ref.file)
ResumeUtil.parseInputStream(inputStream)
}
Ok(Json.toJson(resume))
}
CommandtoPlaywithLargeMemory
>sbtcleanupdatecompiledist
>bin/classifier-play-Dconfig.file=conf/application.conf-Dhttp.port=8003-Dhttp.address=0.0.0.0-J-Xms1024M-J-Xmx8g-J-server
References:
http://stackoverflow.com/questions/3938569/how-do-i-upload-a-file-with-metadata-using-a-rest-web-service
http://stackoverflow.com/questions/4083702/posting-a-file-and-data-to-restful-webservice-as-json
FileUploadforScala
https://www.playframework.com/documentation/2.4.3/ScalaFileUpload
http://stackoverflow.com/questions/9452375/how-to-get-the-upload-file-with-other-inputs-in-play2