Playframework and FileUpload in RESTful

本文详细介绍了在 RESTful API 中实现文件上传的方法,包括 Base64 编码、多部分表单数据发送以及使用 Play Framework 的文件上传功能。同时,文章提供了日志配置示例、文件上传命令及路由配置建议。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Playframework and FileUpload in RESTful

File Upload in RESTful API right now, there are only 3 options till now.
1. Base64 encode the file, at the expense of increasing the data size by around 33%.
2. Send the file first in a multipart/form-data POST, and return and ID to the client. The client then sends the metadata with the ID. The server re-associates the file and the metadata.
3. Send the metadata first, and return an ID to the client. The client then sends the file with the ID, and the server re-associates the file and the metadata.

I may choose #2 or #3. Looking at play framework Uploading Files Chapter.

1. Playframework File Upload
I will use “multipart/form-data” encoding to make the form support mix standard form data with file attachment data.

Logging Level
ch.qos.logback.classic.Level TRACE, DEBUG, INFO, WARN and ERROR
https://www.playframework.com/documentation/2.4.3/SettingsLogger
https://www.playframework.com/documentation/2.4.3/ScalaLogging

def upload = Action(parse.multipartFormData) { request =>
request.body.file("file").map { file =>
import java.io.File
val filename = file.filename
val contentType = file.contentType
Ok("Resume there.")
}.getOrElse {
BadRequest(Json.obj("status" -> "OK", "message" -> "No files in the attachment."))
}
}

I was originally thinking that I may separate it into 2 steps. 1 - uploading file, 2 - parse file. But after think about this again. I may change that to 1 single step.

2. Directly Upload the File and Other Params
route configuration to upload the file content

# Resume Routes
POST /api/v1/resume/parseFile controllers.ResumeController.parseFile()
POST /api/v1/resume/parseContent controllers.ResumeController.parseContent()

The logging configuration
<configuration>

<conversionRule conversionWord="coloredLevel" converterClass="play.api.Logger$ColoredLevel" />

<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>logs/application.log</file>
<encoder>
<pattern>%date [%level] from %logger in %thread - %message%n%xException</pattern>
</encoder>
</appender>

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%coloredLevel %logger{15} - %message%n%xException{10}</pattern>
</encoder>
</appender>

<appender name="ASYNCFILE" class="ch.qos.logback.classic.AsyncAppender">
<appender-ref ref="FILE" />
</appender>

<appender name="ASYNCSTDOUT" class="ch.qos.logback.classic.AsyncAppender">
<appender-ref ref="STDOUT" />
</appender>

<logger name="play" level="INFO" />
<logger name="application" level="DEBUG" />

<!-- Off these ones as they are annoying, and anyway we manage configuration ourself -->
<logger name="com.avaje.ebean.config.PropertyMapLoader" level="OFF" />
<logger name="com.avaje.ebeaninternal.server.core.XmlConfigLoader" level="OFF" />
<logger name="com.avaje.ebeaninternal.server.lib.BackgroundThread" level="OFF" />
<logger name="com.gargoylesoftware.htmlunit.javascript" level="OFF" />
<logger name="controllers.ResumeController" level="DEBUG" />

<root level="WARN">
<appender-ref ref="ASYNCFILE" />
<appender-ref ref="ASYNCSTDOUT" />
</root>

</configuration>

Implementation Class to Deal with File

import java.io.FileInputStream

import com.wordnik.swagger.annotations._
import utils.IncludeLogger

import play.api.libs.json.{JsError, Json}
import play.api.mvc.{BodyParsers, Action, Controller}

…snip...
implicit val resumeWrites = Json.writes[Resume]
implicit val resumeReads = Json.reads[Resume]

@ApiOperation(value = "parseFile",
notes = "Parse the Resume File",
response = classOf[Resume],
httpMethod = "POST",
produces = "json",
position = 1)
@ApiImplicitParams(Array(
new ApiImplicitParam(
name="body",
value = "Resume File",
required = true,
dataType = "file",
paramType = "body")))
@ApiResponses(Array(new ApiResponse(code = 200, message = "Successful Parse Resume.", response = classOf[Resume]) ))
def parseFile = Action(parse.multipartFormData) { request =>
logger.debug("The request is here.")
val resume = request.body.files.map { file =>
val filename = file.filename
logger.debug("file: " + filename + " " + file.contentType)
val inputStream = new FileInputStream(file.ref.file)
ResumeUtil.parseInputStream(inputStream)
}
Ok(Json.toJson(resume))
}

Command to Play with Large Memory
>sbt clean update compile dist
>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

File Upload for Scala
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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值