IBM Mobilefirst Java HTTP Adapter 中的多部分文件上传

Posted

技术标签:

【中文标题】IBM Mobilefirst Java HTTP Adapter 中的多部分文件上传【英文标题】:Multipart file upload in IBM Mobilefirst Java HTTP Adapter 【发布时间】:2020-09-03 03:30:52 【问题描述】:

我是 IBM Mobile-first java 适配器的新手,我正在尝试使用 Postman 将图像文件(Multipart 请求)发送到我的 java 适配器(使用 JAX-Rs),并在 Rest API 中接收该图像文件,并且将其发送到第三方服务器。

但是,每当我从 Postman 访问 API 时,我都会收到 415 Unsupported media type 错误,我什至尝试在 MFPJAXRSApplication 类中配置 JAX-rs2.0,但这也不起作用。谁能帮我解决这个问题。

我的主要应用类

package com.sample.adapter;

import java.util.logging.Logger;
import com.ibm.mfp.adapter.api.MFPJAXRSApplication;

public class JavaAdapterApplication extends MFPJAXRSApplication

    static Logger logger = Logger.getLogger(JavaAdapterApplication.class.getName());

    @Override
    protected void init() throws Exception 
        logger.info("Adapter initialized!");
    

    @Override
    protected String getPackageToScan() 
        //The package of this class will be scanned (recursively) to find JAX-RS 2.0 resources.
        return getClass().getPackage().getName();
    

    @Override
    public Set<Class<?>> getClasses() 
        
        
        log.info("********* added this part by following few suggestin of stack overflow ************");
        Set<Class<?>> resources = new java.util.HashSet<Class<?>>();
        resources.add(MultiPartFeature.class);
        addRestResourceClasses(resources);
        return resources;
    

    /**
     * Do not modify addRestResourceClasses() method. It is automatically populated
     * with all resources defined in the project. If required, comment out calling
     * this method in getClasses().
     */
    private void addRestResourceClasses(Set<Class<?>> resources) 
        log.info("********* added this part by following few suggestin of stack overflow ************");
        resources.add(com.adapter.application.services.TestService.class);
    

我的资源类是当我从代码中删除 FormDataContentDisposition 并只保留 Inputstrem 时,我可以访问 API,但一旦添加 FormDataContentDisposition,它就会以 415 不支持的媒体类型错误开始。

import java.awt.AlphaComposite;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.apache.http.client.methods.HttpRequestBase;

import com.adapter.util.CRGEHttpRequestGenerator;
import com.adapter.util.CRGELogUtils;
import com.adapter.util.CRGERequestHandler;
import com.adapter.util.CRGEResponseHandler;
import com.ibm.mfp.adapter.api.ConfigurationAPI;
import com.ibm.mfp.adapter.api.OAuthSecurity;
import com.ibm.mfp.server.security.external.resource.AdapterSecurityContext;

import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataMultiPart;
import org.glassfish.jersey.media.multipart.FormDataParam;

@Path("/hi")   
public class TestService extends RequestHandler  
    @Context
    AdapterSecurityContext securityContext;
    
    @Context
    static ConfigurationAPI configurationAPI;

    static org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(TestService.class.getName());
 

   @POST
@Path("/uploadFeedback")
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces("*/*")
@OAuthSecurity(enabled=false)
public Response  attachupload( @FormDataParam("file") InputStream uploadedInputStream,
        @FormDataParam("file") FormDataContentDisposition fileDetail)
    log.info("fileName"+fileDetail);
    return Response.ok().build();

Pom.xml

    <properties>
        <!-- Use UTF-8 as the encoding of the adapter -->
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

        
    </properties>

     <dependencies>
        <!-- https://mvnrepository.com/artifact/com.ibm.mfp/adapter-maven-api -->
        <dependency>
            <groupId>com.ibm.mfp</groupId>
            <artifactId>adapter-maven-api</artifactId>
            <version>8.0.2018071507</version>
            <scope>provided</scope>
        </dependency>
        
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>3.0.4.RELEASE</version>
            <type>jar</type>
        </dependency>
        
        <!-- https://mvnrepository.com/artifact/log4j/log4j -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
        
        <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-io -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-io</artifactId>
            <version>1.3.2</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.9.7</version>
        </dependency>
        
        <!-- https://mvnrepository.com/artifact/com.ibm.mfp/mfp-java-token-validator -->
        <dependency>
            <groupId>com.ibm.mfp</groupId>
            <artifactId>mfp-java-token-validator</artifactId>
            <version>8.0.2017020112</version>
        </dependency>
        
        <!-- https://mvnrepository.com/artifact/com.ibm.mfp/mfp-security-checks-base -->
        <dependency>
            <groupId>com.ibm.mfp</groupId>
            <artifactId>mfp-security-checks-base</artifactId>
            <version>8.0.2018030404</version>
        </dependency>
        
        <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.8.5</version>
        </dependency>

    
    <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpmime -->
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpmime</artifactId>
    <version>4.3.1</version>
</dependency>
    
   
   
     <dependency>
            <groupId>org.glassfish.jersey.containers</groupId>
            <artifactId>jersey-container-servlet</artifactId>
            <version>2.7</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.media</groupId>
            <artifactId>jersey-media-multipart</artifactId>
            <version>2.7</version>
        </dependency>     

    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>com.ibm.mfp</groupId>
                <artifactId>adapter-maven-plugin</artifactId>
                <extensions>true</extensions>
            </plugin>
        </plugins>
    </build>
</project>

我想知道为什么服务器无法识别 Multipart 请求,我们是否必须配置适配器以接受 multipart 请求,如果是,那么我们如何配置它?任何人都可以通过帮助我来挽救我的生命。

另外,我的应用程序没有 WEB.xml 或任何以 @ApplicationPath 开头的类

【问题讨论】:

在返回此响应之前是否会引发服务器端错误/异常? Mobile-First 是否使用 Jersey 实现来支持其 JAX-RS? 当您省略 FormDataContentDisposition 时,请求正文会显示什么?它只是“文件”部分的内容还是完整的多部分实体?我假设后者。在这种情况下,@FormDataParam 注释将被忽略。当您省略第二个参数时,第一个参数被简单地视为整个身体。除非与 Jersey 一起使用,否则 Jersey 的 Multipart 支持将不起作用。 我已经在适配器应用程序 MFPJAXRSApplication 类中配置了球衣 .. 并且在 mave 文件中导入了球衣依赖,但同样的问题仍然存在 你可以注入HttpServletRequest。您可以查看one of these options 是否适用于制作多部分端点。 【参考方案1】:

您可以使用 org.apache.commons.fileupload 库。适用于 IBM MobileFirst 适配器的示例代码。 要处理文件,请遵循 apache 文档。

@POST
@Path("attachment")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadAttachment() 
    try 
        FileUploadUtil fileUploadUtil = new FileUploadUtil();
        List<FileItem> items = new ServletFileUpload(fileUploadUtil.createDiskFileItemFactory())
                .parseRequest(request);
        Optional<FileItem> file = fileUploadUtil.findFileItem(items, "file");
        //Your custom logic ....
     catch (FileUploadException | IOException | MobileException e) 
        // ....
    

从上下文注入请求的地方:

@Context
private HttpServletRequest request;

【讨论】:

以上是关于IBM Mobilefirst Java HTTP Adapter 中的多部分文件上传的主要内容,如果未能解决你的问题,请参考以下文章

IBM-Mobilefirst 意外错误中的推送通知

Bluemix 的 ibm-mobilefirst-starter 容器 - 添加新的 http 适配器不起作用

IBM MobileFirst:在命令行构建期间使用外部 jar 文件

IBM Mobilefirst Java Adapter 连接 Couchbase

IBM Mobilefirst Java 适配器会话超时

IBM mobilefirst http 适配器无法访问 pdf 附件