杰瑞科技汇

Java Webservice文件上传如何实现?

核心概念

在 WebService 中上传文件,本质上就是客户端将文件数据作为请求的一部分发送给服务器端,服务器端接收并处理这些数据,主要有两种技术实现方式:

Java Webservice文件上传如何实现?-图1
(图片来源网络,侵删)
  1. SOAP (Simple Object Access Protocol) with MTOM (Message Transmission Optimization Mechanism)

    • SOAP: 一种基于 XML 的协议,用于在 Web 上交换结构化信息,传统的 SOAP 消息是纯文本的,如果直接将二进制文件(如图片、视频)编码成 Base64 嵌入 XML 中,会导致消息体积急剧增大,效率低下。
    • MTOM: 是 SOAP 1.2 规范的一部分,专门用于解决二进制数据传输的效率问题,它的工作原理是:
      • 文件数据不会被编码到 XML 主消息体中。
      • 文件数据作为独立的 MIME 部分(MimePart)附加在 SOAP 消息之后。
      • SOAP 消息中只包含一个指向这个 MIME 部分的引用(一个 Content-ID)。
    • 优点: 标准化、安全、可靠,适合企业级应用,对于大文件传输,效率远高于 Base64。
    • 缺点: 配置相对复杂,消息结构比 REST 更臃肿。
  2. REST (Representational State Transfer)

    • REST: 一种更轻量级的架构风格,通常通过 HTTP 协议直接传输数据。
    • 文件上传通常使用 multipart/form-data 格式的 POST 请求,这与在传统 Web 表单中上传文件的方式完全相同。
    • 优点: 简单、灵活、易于调试(可以直接用浏览器或 Postman 测试)、性能通常更好。
    • 缺点: 无状态,安全性需要自己实现(如使用 Token 认证),不如 SOAP 规范严谨。

选择建议:

  • 如果你的项目已经基于 SOAP 架构,或者需要 WS-Security 等高级 SOAP 特性,请选择 MTOM
  • 如果你在构建新的、现代的 API,或者更看重开发效率和简洁性,REST 是更主流和推荐的选择。

使用 JAX-WS + MTOM 实现文件上传 (SOAP)

这里我们使用 JAX-WS(Java API for XML Web Services),这是 Java 标准的 SOAP 实现,我们将使用 Metro 作为实现框架(通常随 JDK 一起提供)。

Java Webservice文件上传如何实现?-图2
(图片来源网络,侵删)

服务端实现

步骤 1: 创建 Maven 项目

pom.xml 中添加依赖:

<dependencies>
    <!-- JAX-WS API -->
    <dependency>
        <groupId>javax.xml.ws</groupId>
        <artifactId>jaxws-api</artifactId>
        <version>2.3.1</version>
    </dependency>
    <!-- JAX-WS RI (Metro) -->
    <dependency>
        <groupId>com.sun.xml.ws</groupId>
        <artifactId>jaxws-rt</artifactId>
        <version>2.3.3</version>
    </dependency>
    <!-- 用于测试服务器 -->
    <dependency>
        <groupId>org.eclipse.jetty</groupId>
        <artifactId>jetty-server</artifactId>
        <version>9.4.44.v20250927</version>
    </dependency>
    <dependency>
        <groupId>org.eclipse.jetty</groupId>
        <artifactId>jetty-servlet</artifactId>
        <version>9.4.44.v20250927</version>
    </dependency>
</dependencies>

步骤 2: 创建数据传输对象

我们需要一个类来接收文件信息,使用 @MTOM 注解是关键,它告诉 JAX-WS 运行时启用 MTOM 优化。

Java Webservice文件上传如何实现?-图3
(图片来源网络,侵删)
import javax.activation.DataHandler;
import javax.xml.bind.annotation.XmlMimeType;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlSeeAlso({ObjectFactory.class})
public class FileTransferRequest {
    private String fileName;
    private String fileType;
    // 使用 DataHandler 来处理二进制数据
    // @XmlMimeType 指定了文件的 MIME 类型
    @XmlMimeType("application/octet-stream")
    private DataHandler fileData;
    // Getters and Setters
    public String getFileName() {
        return fileName;
    }
    public void setFileName(String fileName) {
        this.fileName = fileName;
    }
    public String getFileType() {
        return fileType;
    }
    public void setFileType(String fileType) {
        this.fileType = fileType;
    }
    public DataHandler getFileData() {
        return fileData;
    }
    public void setFileData(DataHandler fileData) {
        this.fileData = fileData;
    }
}

步骤 3: 创建 WebService 接口

import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.xml.ws.soap.MTOM;
// @MTOM 注解启用 MTOM
@MTOM
// @WebService 指定这是一个 WebService
@WebService
// @SOAPBinding.Style.DOCUMENT 表示使用文档风格的 SOAP 消息
@SOAPBinding(style = SOAPBinding.Style.DOCUMENT)
public interface FileUploadService {
    @WebMethod
    String uploadFile(FileTransferRequest request);
}

步骤 4: 实现 WebService

import javax.activation.DataHandler;
import javax.jws.WebService;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@WebService(endpointInterface = "com.example.FileUploadService")
public class FileUploadServiceImpl implements FileUploadService {
    @Override
    public String uploadFile(FileTransferRequest request) {
        String fileName = request.getFileName();
        DataHandler dataHandler = request.getFileData();
        // 定义服务器上保存文件的目录
        String uploadDir = "uploads/";
        File uploadDirFile = new File(uploadDir);
        if (!uploadDirFile.exists()) {
            uploadDirFile.mkdirs();
        }
        String filePath = uploadDir + fileName;
        try (InputStream is = dataHandler.getInputStream();
             OutputStream out = new FileOutputStream(filePath)) {
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = is.read(buffer)) != -1) {
                out.write(buffer, 0, bytesRead);
            }
            System.out.println("文件上传成功: " + filePath);
            return "文件 " + fileName + " 上传成功!保存在: " + filePath;
        } catch (IOException e) {
            e.printStackTrace();
            return "文件上传失败: " + e.getMessage();
        }
    }
}

步骤 5: 发布 WebService

我们可以使用一个简单的 Jetty 服务器来发布这个服务。

import com.sun.xml.ws.transport.http.servlet.WSServlet;
import com.sun.xml.ws.transport.http.servlet.WSServletContextListener;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import javax.xml.ws.Endpoint;
import java.io.File;
public class FileUploadPublisher {
    public static void main(String[] args) throws Exception {
        // 1. 发布方式一:使用 Endpoint.publish (简单,适合测试)
        /*
        String address = "http://localhost:8080/FileUploadService";
        FileUploadService serviceImpl = new FileUploadServiceImpl();
        Endpoint.publish(address, serviceImpl);
        System.out.println("SOAP Service 已发布在: " + address);
        System.out.println("按任意键停止服务...");
        System.in.read();
        */
        // 2. 发布方式二:使用 Servlet 容器 (如 Jetty, Tomcat,更灵活)
        Server server = new Server(8080);
        ServletContextHandler context = new ServletContextHandler();
        context.setContextPath("/");
        server.setHandler(context);
        // 添加 WSServlet
        ServletHolder holder = new ServletHolder(new WSServlet());
        holder.setName("FileUploadService");
        // 指定实现类
        holder.setInitParameter("javax.xml.ws.servlet.endpoint-class", "com.example.FileUploadServiceImpl");
        context.addServlet(holder, "/FileUploadService/*");
        // 添加监听器
        context.addEventListener(new WSServletContextListener());
        server.start();
        System.out.println("SOAP Service 已发布在: http://localhost:8080/FileUploadService");
        System.out.println("按 Ctrl+C 停止服务...");
        server.join();
    }
}

注意: 要让 WSServlet 正常工作,你需要在 WEB-INF/web.xml 中配置,但使用 Metro 的 WSServletContextListener 可以自动完成大部分配置,上面的代码是简化的。


使用 JAX-RS (REST) 实现文件上传

这里我们使用 JAX-RS(Java API for RESTful Web Services),标准实现是 Jersey。

服务端实现

步骤 1: 创建 Maven 项目

pom.xml 中添加依赖:

<dependencies>
    <!-- Jersey 核心依赖 -->
    <dependency>
分享:
扫描分享到社交APP
上一篇
下一篇