使用 Meta-Data (`multipart/form-data`) 将文件上传到 ColdFusion 11 REST 服务

Upload File with Meta-Data (`multipart/form-data`) to ColdFusion 11 REST Service

如何在 ColdFusion 11 REST 服务中访问通过文件上传(使用 enctype="multipart/form-data")发送的 meta-data(表单数据)?

模拟一个简单的服务:

component
  restpath = "test"
  rest     = true
{
  remote void function upload(
    required numeric id       restargsource = "Path",
    required any     document restargsource = "Form",
    required string  title    restargsource = "Form"
  )
    httpmethod = "POST"
    restpath   = "{id}/"
    produces   = "application/json"
  {
    if ( FileExists( document ) )
      restSetResponse({
        "status"  = 201,
        "content" = {
          "id"    = id,
          "title" = title,
          "size"  = GetFileInfo( document ).size
        }
      });
    else
      restSetResponse({
        "status"  = 400,
        "content" = "Nothing uploaded"
      });
  }
}

和一个简单的 HTML 文件来测试它:

<!DOCTYPE html>
<html>
<body>
<form method="post"
      action="http://localhost/rest/TestService/test/1/"
      enctype="multipart/form-data">
<input type="text" name="title"    value="File Title" /><br />
<input type="file" name="document" /><br />
<button type="submit">Submit</button>
</form>
</body>
</html>

然后服务 returns 一个 500 HTTP 状态代码和 JSON 响应:

{"Message":"The DOCUMENT parameter to the upload function is required but was not passed in."}

检查 HTTP 请求 headers 显示两个字段都已传入,但服务未接收到它们。

注释掉 HTML 表单中的 enctype 属性(因此它使用 application/x-www-form-urlencoded 的默认编码)然后服务 returns a 400 HTTP 状态代码和响应 Nothing uploaded.

如何解决?

为了彻底混淆请求数据填充 FORM 变量,但是,即使函数参数声明 restargsource="form",当 enctype 不是 application/x-www-form-urlencoded.

Adobe 的 Getting started with RESTful web services in ColdFusion 文章证实了这一点:

Form parameters:

In many scenarios, you must process data that you enter in the form in a REST service. You can use this data to make a new entry ( POST ) or update an existing record ( PUT ) in the database. If you use form fields, set restargsource to form . This extracts the data present in the request and makes it available for further processing. Also, you must set the content-type header to application/x-www-form-urlencoded when sending data as form fields.

但是,可以通过将使用 restargsource="form" 的参数更改为明确限定在 form 变量范围内的参数来解决。

所以,像这样修改服务:

component
  restpath = "test"
  rest     = true
{
  remote void function upload(
    required numeric id       restargsource = "Path"
  )
    httpmethod = "POST"
    restpath   = "{id}/"
    produces   = "application/json"
  {
    param name="form.document" type="string";
    param name="form.title"    type="string";

    if ( FileExists( form.document ) )
      restSetResponse({
        "status"  = 201,
        "content" = {
          "id"    = id,
          "title" = form.title,
          "size"  = GetFileInfo( form.document ).size
        }
      });
    else
      restSetResponse({
        "status"  = 400,
        "content" = "Nothing uploaded"
      });
  }
}