REST Web service: Upload và Download file với Jersey 2.x

Trong các bài viết trước, chúng ta đã cùng tìm hiểu cách xây dựng ứng dụng CRUD với RESTful Web service. Trong bài này, chúng ta cùng tìm hiểu cách upload/ download file với RESTful sử dụng Jersey version 2.x như thế nào.

1. Tạo Jersey project

Chúng ta sẽ sử dụng lại project Jersey 2.x ở bài trước.

Để có thể upload/ download file với Jersey, chúng ta khai báo thêm thư viện sau trong file pom.xml.

<!-- https://mvnrepository.com/artifact/org.glassfish.jersey.media/jersey-media-multipart -->
<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-multipart</artifactId>
    <version>${jersey.version}</version>
</dependency>

Đăng ký sử dụng MultiPartFeature: chúng ta có thể sử dụng một trong 2 cách sau:

  • Thêm cấu hình trong file JerseyServletContainerConfig.java
  • Thêm cấu hình trong file web.xml

JerseyServletContainerConfig.java

package com.maixuanviet.config;
 
import java.util.logging.Level;
import java.util.logging.Logger;
 
import org.glassfish.jersey.jackson.JacksonFeature;
import org.glassfish.jersey.logging.LoggingFeature;
import org.glassfish.jersey.media.multipart.MultiPartFeature;
//Deployment of a JAX-RS application using @ApplicationPath with Servlet 3.0
//Descriptor-less deployment
import org.glassfish.jersey.server.ResourceConfig;
 
public class JerseyServletContainerConfig extends ResourceConfig {
    public JerseyServletContainerConfig() {
        // if there are more than two packages then separate them with semicolon
        packages("com.maixuanviet.api");
        register(new LoggingFeature(Logger.getLogger(LoggingFeature.DEFAULT_LOGGER_NAME), Level.INFO,
                LoggingFeature.Verbosity.PAYLOAD_TEXT, 10000));
        register(JacksonFeature.class); 
        register(MultiPartFeature.class);   
    }
}

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0">
    <display-name>RESTful CRUD Example by maixuanviet</display-name>
    <servlet>
        <servlet-name>jersey2-serlvet</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>javax.ws.rs.Application</param-name>
            <param-value>com.maixuanviet.config.JerseyServletContainerConfig</param-value>
        </init-param>
        <init-param>
                    <param-name>jersey.config.server.provider.classnames</param-name>
                    <param-value>org.glassfish.jersey.filter.LoggingFilter;
                        org.glassfish.jersey.jackson.JacksonFeature;
                        org.glassfish.jersey.media.multipart.MultiPartFeature</param-value>
            </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>jersey2-serlvet</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>
</web-app>

2. Tạo Java REST Web service cho phép upload/ download file với Jersey2

FileService.java

Tạo file FileUploadResponse.java, file này chứa thông tin trả về cho Client sau khi đã upload thành công:

package com.maixuanviet.model;
 
import java.util.Date;
 
import lombok.Data;
 
@Data
public class FileUploadResponse {
 
    private String fileName;
    private Date createdDate;
    private long fileSizeInByte;
}

Tạo REST web service cho phép upload/ download file:

package com.maixuanviet.api;
 
import java.io.File;
import java.io.InputStream;
import java.util.Date;
 
import javax.activation.MimetypesFileTypeMap;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
 
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam;
 
import com.maixuanviet.model.FileUploadResponse;
import com.maixuanviet.utils.FileUtils;
 
//URI:
//http(s)://<domain>:(port)/<YourApplicationName>/<UrlPattern in web.xml>/<path>
//http://localhost:8080/RestfulWebServiceExample/rest/files
@Path("/files")
public class FileService {
 
    public static final String BASE_FOLDER = "D:/WorkSpace/maixuanviet/Java-Tutorial/Jersey2RestfulWebServiceExample/data/";
 
    @GET
    @Path("/download/{type}")
    public Response downloadFile(@PathParam("type") String fileType) {
 
        String fileName = "test." + fileType;
        File file = new File(BASE_FOLDER + "download/" + fileName);
 
        /* Finding MIME type for explicitly setting MIME */
        String mimeType = new MimetypesFileTypeMap().getContentType(file);
 
        ResponseBuilder responseBuilder = Response.ok(file, mimeType);
        responseBuilder.header("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
        return responseBuilder.build();
    }
 
    @POST
    @Path("/upload")
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
    public Response uploadFile( //
            @FormDataParam("uploadFile") InputStream fileInputStream,
            @FormDataParam("uploadFile") FormDataContentDisposition fileFormDataContentDisposition) {
 
        String fileName = fileFormDataContentDisposition.getFileName();
        File uploadedFile = FileUtils.storeFile(fileInputStream, BASE_FOLDER, fileName);
 
        FileUploadResponse entity = new FileUploadResponse();
        entity.setFileName(uploadedFile.getName());
        entity.setFileSizeInByte(uploadedFile.length());
        entity.setCreatedDate(new Date());
        System.out.println("entity: " + entity);
 
        return Response.ok("File uploaded successfully at " + uploadedFile.getPath()).entity(entity).build();
    }
}

Lớp hỗ trợ lưu file trên server từ một InputStream:

FileUtils.java

package com.maixuanviet.utils;
 
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Paths;
 
public class FileUtils {
     
    private FileUtils() {
        super();
    }
 
    public static File storeFile(InputStream inputStream, String baseFolder, String fileName) {
        String extension = fileName.substring(fileName.lastIndexOf('.'));
        String name = fileName.substring(0, fileName.lastIndexOf('.'));
        String uploadedFilePath = baseFolder + "upload/" + name + "-" + System.currentTimeMillis() + extension;
 
        File uploadedFile = new File(Paths.get(uploadedFilePath).toAbsolutePath().toString());
        try (OutputStream outputStream = new FileOutputStream(uploadedFile)) {
            int read = 0;
            byte[] bytes = new byte[1024];
            while ((read = inputStream.read(bytes)) != -1) {
                outputStream.write(bytes, 0, read);
            }
            outputStream.flush();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        return uploadedFile;
    }
}

3. Test Upload/ Download file với RESTful web service sử dụng Postman

  • (1) : Chọn phương thức POST upload file mà REST service support.
  • (2) : Nhập địa chỉ resource.
  • (3) : Chọn tab Header.
  • (4) : Thêm header để chỉ định kết quả trả về là XML (Accept: application/xml). Nếu muốn kết quả trả về là json thì thay đổi giá trị Acccept: application/json.
  • (5) : Chọn tab Body.
  • (6) : Chọn enctype là multipart/form-data.
  • (7) : Nhập key uploadFile, key này tương ứng với đối số mà web service nhận dữ liệu.
  • (8) : Chọn loại control là Upload.
  • (9) : Chọn file để test.
  • (10) : Gửi request.
  • (11) : Kết quả trả về.

4. Tạo Java REST Client truy cập web servcie với Jersey2 Client

4.1. Tạo Jersey Client upload file

UploadFileWithJerseyRestClientExample.java

package com.maixuanviet.client;
 
import java.io.File;
import java.io.IOException;
 
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
 
import org.glassfish.jersey.media.multipart.FormDataMultiPart;
import org.glassfish.jersey.media.multipart.MultiPart;
import org.glassfish.jersey.media.multipart.MultiPartFeature;
import org.glassfish.jersey.media.multipart.file.FileDataBodyPart;
 
import com.maixuanviet.model.FileUploadResponse;
 
public class UploadFileWithJerseyRestClientExample {
 
    public static final String API_URL = "http://localhost:8080/RestfulWebServiceExample/rest/files/upload";
 
    public static final String BASE_FOLDER = "D:/WorkSpace/maixuanviet/Java-Tutorial/Jersey2RestfulWebServiceExample/data/";
 
    public static void main(String[] args) throws IOException {
 
        File testFile = new File(BASE_FOLDER + "test.jpg");
        FileDataBodyPart filePart = new FileDataBodyPart("uploadFile", testFile);
         
        try (FormDataMultiPart formDataMultiPart = new FormDataMultiPart();
            MultiPart multipart = formDataMultiPart.bodyPart(filePart);) {
 
            Client client = ClientBuilder.newBuilder().register(MultiPartFeature.class).build();
            WebTarget target = client.target(API_URL);
            Response response = target.request(MediaType.APPLICATION_JSON_TYPE).post(Entity.entity(multipart, multipart.getMediaType()));
     
            FileUploadResponse result = response.readEntity(FileUploadResponse.class);
            System.out.println("result: " + result);
        }
    }
}

4.2. Tạo Jersey Client download file

DownloadFileWithJerseyRestClientExample.java

package com.maixuanviet.client;
 
import java.io.File;
import java.io.InputStream;
 
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Response;
 
import org.glassfish.jersey.media.multipart.MultiPartFeature;
 
import com.maixuanviet.utils.FileUtils;
 
public class DownloadFileWithJerseyRestClientExample {
 
    public static final String API_URL = "http://localhost:8080/RestfulWebServiceExample/rest/files/download/";
 
    public static final String BASE_FOLDER = "D:/WorkSpace/maixuanviet/Java-Tutorial/Jersey2RestfulWebServiceExample/data/";
 
    public static void main(String[] args) {
 
        Client client = ClientBuilder.newBuilder().register(MultiPartFeature.class).build();
        WebTarget target = client.target(API_URL + "docx");
        Response resp = target.request().get();
 
        if (resp.getStatus() == Response.Status.OK.getStatusCode()) {
            InputStream is = resp.readEntity(InputStream.class);
            File uploadedFile = FileUtils.storeFile(is, BASE_FOLDER, "test-download.docx");
            System.out.println("uploadedFile: " + uploadedFile.getAbsolutePath());
        } else {
            System.out.println("Http Call failed. The response code is" + resp.getStatus() + //
                    ". Error reported is" + resp.getStatusInfo());
        }
    }
}

Related posts:

Java Program to Implement Find all Forward Edges in a Graph
Spring WebClient Requests with Parameters
Java Program to Create a Minimal Set of All Edges Whose Addition will Convert it to a Strongly Conne...
Object Type Casting in Java
Hướng dẫn Java Design Pattern – Builder
Java Program to Implement ArrayDeque API
Spring Boot - Tracing Micro Service Logs
Java Program to Implement ConcurrentSkipListMap API
Java Program to Generate Random Numbers Using Probability Distribution Function
Spring Boot - Enabling Swagger2
Java Program to Implement Hamiltonian Cycle Algorithm
Merging Two Maps with Java 8
Generating Random Dates in Java
Spring Boot: Customize Whitelabel Error Page
Spring Security 5 for Reactive Applications
Tìm hiểu cơ chế Lazy Evaluation của Stream trong Java 8
Java Program to Find the Longest Subsequence Common to All Sequences in a Set of Sequences
Spring Data JPA and Null Parameters
Java – Write an InputStream to a File
Updating your Password
Java Program to Perform Quick Sort on Large Number of Elements
Java Program to Implement Hash Tables chaining with Singly Linked Lists
Java Program to Print the Kind of Rotation the AVL Tree is Undergoing
Java Program to Check if a Directed Graph is a Tree or Not Using DFS
Java Multi-line String
Java Program to Implement Weight Balanced Tree
Constructor Dependency Injection in Spring
A Quick Guide to Spring MVC Matrix Variables
Java Program to Implement a Binary Search Tree using Linked Lists
Java Program to Implement Sieve Of Eratosthenes
How to Break from Java Stream forEach
A Guide to TreeMap in Java