2

我正在开发一个托管在 Liberty 服务器上的 REST 应用程序,该应用程序应该允许支持文件上传。作为此 POST 请求的一部分,我希望允许用户使用表单参数指定一些内容。尽管在这里使用了 IBM 的示例,但我还是无法让它发挥作用。我可以使用标题检索与上传文件相关的信息(如示例中所示)。但是当我尝试使用相同的方法来检索有关标头的信息时,唯一可用的是字段的名称,而不是它们的值。
我也在努力保持对 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”表单参数的唯一信息是参数的名称是“archive_name”。如何获取与“archive_name”关联的值?

4

1 回答 1

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 标头内,而是像在“部分”的“正文”中一样。较旧的 WebSphere JAX-RS 基于 Apache Wink 而不是 CXF,实际上有一个 part.getBody() 方法,这对我们有用。

如果我使用浏览器开发人员工具来查看此类表单的实际 POST 内容,那么额外的参数如下所示:

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

Joe Smith

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

于 2018-01-27T15:26:50.807 回答