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:

Spring Data MongoDB – Indexes, Annotations and Converters
Hướng dẫn sử dụng Printing Service trong Java
Java Program to Implement Adjacency Matrix
Introduction to Spring MVC HandlerInterceptor
Giới thiệu java.io.tmpdir
Debugging Reactive Streams in Java
Spring Boot - Enabling Swagger2
Java Program to Implement Park-Miller Random Number Generation Algorithm
Giới thiệu thư viện Apache Commons Chain
Spring Boot Gradle Plugin
Java Program to Create a Random Linear Extension for a DAG
Java Program to Perform Finite State Automaton based Search
How to use the Spring FactoryBean?
Java Program to Implement Skew Heap
Java Program to Describe the Representation of Graph using Incidence Matrix
How to Manually Authenticate User with Spring Security
Java Program to Implement Brent Cycle Algorithm
Java Program to Solve Knapsack Problem Using Dynamic Programming
Chuyển đổi Array sang ArrayList và ngược lại
Convert XML to JSON Using Jackson
Java Program to Find the Minimum Element of a Rotated Sorted Array using Binary Search approach
Vòng lặp for, while, do-while trong Java
Spring Security Custom AuthenticationFailureHandler
Collection trong java
Java Program to Implement Sorted List
Server-Sent Events in Spring
HttpClient 4 – Send Custom Cookie
Hướng dẫn sử dụng Java String, StringBuffer và StringBuilder
Chương trình Java đầu tiên
Java Program to Implement Interpolation Search Algorithm
Java Program to Implement Sorted Circular Doubly Linked List
Batch Processing with Spring Cloud Data Flow