如何通过多部分文件上传接受表单参数

时间:2018-01-25 19:51:41

标签: java jax-rs websphere swagger open-liberty

我正在开发一个Liberty服务器上托管的REST应用程序,该应用程序应该允许支持文件上载。作为此POST请求的一部分,我想允许用户使用Form参数指定一些内容。尽管使用了IBM here中的示例,但我还是无法使用它。我可以使用标题检索与上传文件相关的信息(如示例中所示)。但是当我尝试使用相同的方法来检索有关标题的信息时,唯一可用的是字段的名称,而不是它们的值。
我也在努力维持对Swagger的支持..
这是我的代码片段:

@ApiOperation("Upload Source Code to Build")
@POST
@Path("/")
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.MULTIPART_FORM_DATA)
@ApiResponses({
    @ApiResponse(code = 200, message= "OK", response=String.class)})
@ApiImplicitParams({
    @ApiImplicitParam(
            name="source", 
            value = "Source File", 
            required = true, 
            dataType = "java.io.File", 
            paramType = "form", 
            type="file"),
    @ApiImplicitParam(
            name="archive_name", 
            value = "Name of File to Retrieve", 
            required = true, 
            dataType = "java.lang.String", 
            paramType = "form", 
            type="string"),
    @ApiImplicitParam(
            name="build_command", 
            value = "Command to Run", 
            required = true, 
            dataType = "java.lang.String", 
            paramType = "form", 
            type="string")})
public Response uploadFileBuildArchive(
        @ApiParam(hidden=true) IMultipartBody multipartBody,
        @Context UriInfo uriInfo) throws IOException {
    List<IAttachment> attachments = multipartBody.getAllAttachments();
    InputStream stream = null;
    Iterator<IAttachment> it = attachments.iterator();
    IAttachment attachment = it.next();

    if (attachment == null)
        return Response.status(400).entity("No file attached").build();

    StringBuilder fileName = new StringBuilder("");
    StringBuilder archiveName = new StringBuilder("");
    StringBuilder buildCommand = new StringBuilder("");

    for(int i = 0; it.hasNext(); i++) {
        DataHandler dataHandler = attachment.getDataHandler();
        MultivaluedMap<String, String> map = attachment.getHeaders();
        String[] contentDisposition = map.getFirst("Content-Disposition").split(";");

        if(i == 0) {
            stream = dataHandler.getInputStream();
            Response saveFileResponse = handleFileStream(contentDisposition, stream, fileName);
            if (saveFileResponse != null)
                return saveFileResponse;
        } else if (i == 1) {
            if (!handleFormParam(contentDisposition, archiveName))
                return Response.status(400).entity("Missing FormParam: archive_name").build();
        }
    .
    .
    .
private boolean handleFormParam(String[] contentDisposition, StringBuilder stringBuilder) {
    String formElementName = null;
    for (String tempName : contentDisposition) {
        String[] names = tempName.split("=");
        for (String n : names) {
            System.out.println(tempName + ":" + n);
        }
    }
    if (stringBuilder.length() == 0) {
        return false;
    }
    return true;
}

我可以从附件获得的关于“archive_name”表单参数的唯一信息是param的名称是“archive_name”。如何获取与“archive_name”关联的值?

1 个答案:

答案 0 :(得分:0)

我认为您说要提交其他文本表单参数以及要上传的文件,对吗?像:

<form action="upload" method="post" enctype="multipart/form-data">
    Name: <input name="myName" type="text"/><br>
    File: <input name="document" type="file"/><br>
    <input type="submit"/>
</form>

如果是这样,虽然我只是在较旧的JAX-RS下完成此操作,但我认为问题在于这些额外的字段值不会到达Content-Disposition标头内,但就像在&#中一样34;主体&#34; &#34;部分&#34;。较旧的WebSphere JAX-RS,基于Apache Wink而不是CXF,实际上有一个part.getBody()方法,这对我们有用。

如果我使用浏览器开发人员工具来观看此类表单的实际POST内容,这就是额外参数的样子:

-----------------------------18059782765430180341846081335
Content-Disposition: form-data; name="myName"

Joe Smith

所以我在那个(显然是特定于IBM的)类IAttachment或者DataHandler上寻找其他方法,它们可能会从部件的主体中获取文本。