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:

RestTemplate Post Request with JSON
Count Occurrences of a Char in a String
Compare Two JSON Objects with Jackson
Java IO vs NIO
Spring Boot Integration Testing with Embedded MongoDB
An Example of Load Balancing with Zuul and Eureka
Lập trình đa luồng trong Java (Java Multi-threading)
Java Map With Case-Insensitive Keys
Spring Boot - Logging
Giới thiệu Google Guice – Injection, Scope
Java Program to Implement Heap
Java Program to Implement Dijkstra’s Algorithm using Queue
Java Program to Implement Flood Fill Algorithm
Các kiểu dữ liệu trong java
Java Program to Implement Range Tree
Spring Boot - Eureka Server
More Jackson Annotations
Spring NoSuchBeanDefinitionException
Prevent Brute Force Authentication Attempts with Spring Security
Java Program to Implement Miller Rabin Primality Test Algorithm
Java Program to Implement TreeMap API
Java Program to Find ith Largest Number from a Given List Using Order-Statistic Algorithm
Quick Guide to Spring MVC with Velocity
Intro to the Jackson ObjectMapper
Java Program to Implement Karatsuba Multiplication Algorithm
Concurrent Test Execution in Spring 5
Java Program to Describe the Representation of Graph using Incidence Matrix
How to Get a Name of a Method Being Executed?
Java TreeMap vs HashMap
Vấn đề Nhà sản xuất (Producer) – Người tiêu dùng (Consumer) và đồng bộ hóa các luồng trong Java
Java Program to Find the Number of Ways to Write a Number as the Sum of Numbers Smaller than Itself
Spring Security 5 – OAuth2 Login