杰瑞科技汇

java webservice 文件上传

  1. 基于 JAX-WS (SOAP) 的文件上传:传统的、基于 XML 的 WebService 方式。
  2. 基于 RESTful (JAX-RS) 的文件上传:现代、轻量级、基于 HTTP 的方式,是目前更推荐的做法。

基于 JAX-WS (SOAP) 的文件上传

SOAP WebService 上传文件通常有两种方式:

java webservice 文件上传-图1
(图片来源网络,侵删)
  • MTOM (Message Transmission Optimization Mechanism)强烈推荐,它是一种 SOAP 扩展,允许在 SOAP 消息中以原始二进制形式(而非 Base64 编码)传输大型附件,这极大地提高了效率和性能。
  • Base64 编码:将文件内容直接编码到 SOAP 消息的 XML 标签中,这种方式简单,但对于大文件,XML 会变得非常臃肿,性能极差,不推荐用于生产环境。

下面我们重点介绍 MTOM 方式。

服务端 (Server Side)

我们将使用 JAX-WS 的参考实现 JAX-WS RI (通常包含在 JDK 中)。

步骤:

  1. 创建一个数据类 (POJO),用于接收文件信息。
  2. 创建一个 WebService 接口,并定义一个用于上传文件的方法。
  3. 实现接口,编写具体的上传逻辑。
  4. 发布 WebService

代码示例:

java webservice 文件上传-图2
(图片来源网络,侵删)

数据类 FileUploadRequest.java

这个类将作为 SOAP 消息的附件容器。

import javax.activation.DataHandler;
import javax.xml.bind.annotation.XmlMimeType;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import java.io.InputStream;
// 使用 @XmlMimeType 注解指定附件的 MIME 类型
public class FileUploadRequest {
    private String fileName;
    private String fileType;
    // DataHandler 是 JAX-WS 处理附件的核心类
    private DataHandler fileData;
    // 构造函数、getters 和 setters
    public FileUploadRequest() {}
    public FileUploadRequest(String fileName, String fileType, DataHandler fileData) {
        this.fileName = fileName;
        this.fileType = fileType;
        this.fileData = fileData;
    }
    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;
    }
    // 一个方便的方法,可以从 DataHandler 获取输入流
    public InputStream getFileInputStream() throws Exception {
        return fileData.getInputStream();
    }
}

WebService 接口 FileUploadService.java

import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
// @WebService 定义这是一个 WebService
@WebService
// @SOAPBinding 定义 SOAP 消息风格,使用 DOCUMENT 表示标准的 SOAP 消息格式。
@SOAPBinding(style = SOAPBinding.Style.DOCUMENT)
public interface FileUploadService {
    // @WebMethod 定义这是一个可以远程调用的方法
    // method = "MTOM" 启用 MTOM 支持,这是关键!
    @SOAPBinding(use = SOAPBinding.Use.LITERAL, mode = SOAPBinding.Mode.PARTIAL)
    @WebMethod
    String uploadFile(FileUploadRequest request);
}

WebService 实现类 FileUploadServiceImpl.java

java webservice 文件上传-图3
(图片来源网络,侵删)
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.webservice.FileUploadService") // 指向接口
public class FileUploadServiceImpl implements FileUploadService {
    @Override
    public String uploadFile(FileUploadRequest request) {
        if (request == null || request.getFileData() == null) {
            return "上传失败:请求为空或未包含文件数据。";
        }
        String fileName = request.getFileName();
        String uploadDir = "C:\\uploads\\"; // 定义服务器上存储文件的目录
        // 确保目录存在
        new File(uploadDir).mkdirs();
        String filePath = uploadDir + fileName;
        try (InputStream is = request.getFileInputStream();
             OutputStream os = new FileOutputStream(filePath)) {
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = is.read(buffer)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            System.out.println("文件 '" + fileName + "' 上传成功,保存在: " + filePath);
            return "文件 '" + fileName + "' 上传成功!";
        } catch (IOException e) {
            e.printStackTrace();
            return "上传失败: " + e.getMessage();
        } catch (Exception e) {
            e.printStackTrace();
            return "上传失败: " + e.getMessage();
        }
    }
}

发布 WebService 的主类 Publisher.java

import javax.xml.ws.Endpoint;
public class Publisher {
    public static void main(String[] args) {
        // 定义 WebService 的发布地址
        String address = "http://localhost:8080/FileUploadService";
        // 创建并发布 WebService
        Endpoint.publish(address, new FileUploadServiceImpl());
        System.out.println("WebService 已发布在: " + address);
        System.out.println("请使用 MTOM 客户端进行调用。");
    }
}

如何运行:

  1. 将以上 Java 文件放在同一个包下(com.example.webservice)。
  2. 编译并运行 Publisher.java
  3. 你的 WebService 已经在 http://localhost:8080/FileUploadService 上运行了。

客户端 (Client Side)

客户端也需要启用 MTOM 支持。

使用 wsimport 生成客户端代码:

在命令行中运行(确保你的服务端正在运行):

wsimport -keep -p com.example.client http://localhost:8080/FileUploadService?wsdl

这会生成一堆客户端所需的 Java 文件(接口、实现类等)。

客户端调用代码 FileUploadClient.java

import com.example.client.FileUploadRequest;
import com.example.client.FileUploadService;
import com.example.client.FileUploadService_Service;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.soap.SOAPBinding;
import java.io.File;
public class FileUploadClient {
    public static void main(String[] args) {
        // 1. 创建服务
        FileUploadService_Service service = new FileUploadService_Service();
        FileUploadService port = service.getFileUploadServicePort();
        // 2. 关键步骤:启用 MTOM
        // 获取 BindingProvider 并设置 MTOM
        BindingProvider bp = (BindingProvider) port;
        SOAPBinding binding = (SOAPBinding) bp.getBinding();
        binding.setMTOMEnabled(true); // 必须设置!
        // 3. 准备要上传的文件
        File fileToUpload = new File("C:\\path\\to\\your\\localfile.txt");
        if (!fileToUpload.exists()) {
            System.out.println("本地文件不存在!");
            return;
        }
        // 4. 创建 DataHandler
        // FileDataSource 将文件绑定到 DataHandler
        DataHandler dataHandler = new DataHandler(new FileDataSource(fileToUpload));
        // 5. 创建请求对象
        FileUploadRequest request = new FileUploadRequest();
        request.setFileName(fileToUpload.getName());
        request.setFileType("text/plain"); // 设置 MIME 类型
        request.setFileData(dataHandler);
        // 6. 调用远程方法
        System.out.println("正在上传文件: " + fileToUpload.getName());
        String response = port.uploadFile(request);
        System.out.println("服务器响应: " + response);
    }
}

基于 RESTful (JAX-RS) 的文件上传

这是目前更流行、更简单的方式,它不依赖 SOAP 协议,直接使用 HTTP POST 请求。

服务端 (Server Side)

我们将使用 Jersey(JAX-RS 的参考实现)作为框架,如果你使用 Spring Boot,集成会更加简单。

依赖 (Maven pom.xml)

<dependencies>
    <!-- Jersey 核心依赖 -->
    <dependency>
        <groupId>org.glassfish.jersey.containers</groupId>
        <artifactId>jersey-container-servlet</artifactId>
        <version>2.39</version>
    </dependency>
    <!-- 支持 multipart/form-data -->
    <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-multipart</artifactId>
        <version>2.39</version>
    </dependency>
    <!-- 如果需要 JSON
分享:
扫描分享到社交APP
上一篇
下一篇