[JAVA] So erreichen Sie den Dateidownload mit Feign

1. Zuallererst

Die Standardfunktion von "Feign" unterstützt keine Operationen von HTTP-Anforderungen, die Binärdateien wie das Herunterladen und Hochladen von Dateien verarbeiten. Dieses Mal möchte ich erklären, wie man den Dateidownload mit Feign realisiert. Die grundlegende Verwendung von "Feign" wird im folgenden Artikel erläutert. Bitte beziehen Sie sich darauf.

2. Definition der Modellklasse

Diese Klasse enthält die Header-, Status- und Antwortgrunddaten, die von feign.Response abgerufen werden können. Es wird davon ausgegangen, dass die Binärdaten einer Datei im Hauptteil der HTTP-Antwort gespeichert sind und nur eine Datei erhalten bleibt. Es ist nicht sehr häufig, aber wenn Sie mehrteilige HTTP-Antworten verarbeiten möchten, ändern Sie sie entsprechend.

FileEntity.java


package com.example.feign.demo.download;

import java.io.File;
import java.io.Serializable;
import java.util.Collection;
import java.util.Map;

public class FileEntity implements Serializable {

    private static final long serialVersionUID = 1L;

    private int status;
    private Map<String, Collection<String>> headers;
    private String reason;
    private File file;

    public FileEntity() {

    }

    public FileEntity(int status, Map<String, Collection<String>> headers,
            String reason, File file) {
        super();
        this.status = status;
        this.headers = headers;
        this.reason = reason;
        this.file = file;
    }

    /**
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append("FileEntity [status=");
        builder.append(status);
        builder.append(", headers=");
        builder.append(headers);
        builder.append(", reason=");
        builder.append(reason);
        builder.append(", file=");
        builder.append(file);
        builder.append("]");
        return builder.toString();
    }

    // setter, getter omitted
}

3. Definition der API-Schnittstelle

Die API ist so einfach wie das Herunterladen einer Datei mit dem angegebenen Pfad. Der Rückgabewert ist die "FileEntity" der zuvor definierten Modellklasse. Wenn "java.io.File" oder "java.nio.file.Path" als Rückgabewert verwendet wird, können keine anderen Informationen als Dateidaten (Header, Statuscode usw.) abgerufen werden, sodass "FileEntity" vorbereitet wird.

DownloadApi.java


package com.example.feign.demo.download;

import feign.Param;
import feign.RequestLine;

public interface DownloadApi {

    @RequestLine("GET {path}")
    FileEntity download(@Param("path") String path);
}

4. Definieren Sie den Decoder für den Dateidownload

Dies ist der Punkt dieses Artikels. Decoder ist verantwortlich für die Datenkonvertierungsverarbeitung (Deserialisierung) der HTTP-Antwort. Implementiert einen "Decoder" für Dateidownloads, der die "feign.codec.Decoder" -Schnittstelle implementiert. Implementieren Sie die gewünschte Verarbeitung in der "Decodierungs" -Methode. Der Rückgabewert dieser Methode ist der Rückgabewert der API-Schnittstelle. Dieses Mal werden die BODY-Daten der Antwort so gespeichert, wie sie sind, da davon ausgegangen wird, dass es sich um eine Datei handelt. Beachten Sie jedoch, dass es bei mehrteiligen HTTP-Antworten erforderlich ist, sie zu analysieren und als mehrere Dateien zu speichern.

FileEntityDecoder.java


package com.example.feign.demo.download;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Type;
import feign.FeignException;
import feign.Response;
import feign.Util;
import feign.codec.DecodeException;
import feign.codec.Decoder;

public class FileEntityDecoder implements Decoder {

    private static final int BUFFER_SIZE = 1 * 1024 * 1024;

    private String filePath;

    public FileEntityDecoder() {

    }

    public FileEntityDecoder(String filePath) {
        this.filePath = filePath;
    }

    /**
     * @see feign.codec.Decoder#decode(feign.Response, java.lang.reflect.Type)
     */
    @Override
    public Object decode(Response response,
            Type type) throws IOException, DecodeException, FeignException {

        if (response.status() == 404) {
            return Util.emptyValueOf(type);
        }
        if (response.body() == null) {
            return null;
        }

        return createFileEntity(response, filePath);
    }

    /**
     * Save download file on instructed filePath.
     * @param response feign's response
     * @param filePath download file path
     * @return FileEntity instance
     * @throws IOException
     */
    private FileEntity createFileEntity(Response response,
            String filePath) throws IOException {

        // 1. create File object on instructed file path or temporary
        File downloadFile = null;
        if (filePath == null) {
            downloadFile = File.createTempFile("download", null);
        } else {
            downloadFile = new File(filePath);
        }

        // 2. copy contents with buffering
        try (InputStream input = new BufferedInputStream(
                response.body().asInputStream());
                OutputStream out = new BufferedOutputStream(
                        new FileOutputStream(downloadFile));) {
            byte[] buffer = new byte[BUFFER_SIZE];
            long total = 0;
            int len = 0;
            while ((len = input.read(buffer)) != -1) {
                out.write(buffer, 0, len);
                out.flush();
                total = total + len;
                // System.out.println("writed : " + total);
            }
        }

        // 3. create FileEntity instance
        return new FileEntity(response.status(), response.headers(),
                response.reason(), downloadFile);
    }
}

5. Probelauf

Geben Sie beim Erstellen einer Instanz der API-Schnittstelle die Instanz des diesmal implementierten "FileEntityDecoder" im Argument der "Decoder" -Methode an. Ich habe ein Beispiel verwendet, um eine PDF-Datei über "Proxy" aus dem Internet herunterzuladen, für die eine Authentifizierung erforderlich ist. Informationen zur Implementierung der Methode "createOkHttpClientCorrespondedProxy", die der Schlüssel zur Unterstützung von "Proxy" ist, finden Sie in Vorheriger Artikel. Bitte ersetzen Sie die Endpunkt-URL "http: // www.example.com" und den Pfad "/ document / 2018 / pdf / sample.pdf" selbst.

DownloadDemo.java


package com.example.feign.demo.download;

import feign.Feign;
import feign.Logger;
import feign.slf4j.Slf4jLogger;
import okhttp3.OkHttpClient;

public class DownloadDemo {

    public static void main(String[] args) {
        // create instance of okhttp3.OkHttpClient corresponded proxy
        OkHttpClient client = createOkHttpClientCorrespondedProxy("yourProxyHost",
                8080, "proxyUserId", "proxyPass");

        // feign use proxy with authentication
        DownloadApi downloadApi = Feign.builder()
                // set instance of feign.Client.OkHttpClient
                .client(new feign.okhttp.OkHttpClient(client))
                .decoder(new FileEntityDecoder()) // use FileEntityDecoder
                .logger(new Slf4jLogger())        // use Slf4j
                .logLevel(Logger.Level.FULL)      // setting log level to most detail
                .target(DownloadApi.class, "http://www.example.com");

        // call api [GET /documents/2018/pdf/sample.pdf]
        FileEntity fileEntity = downloadApi.download(
                "/document/2018/pdf/sample.pdf");
        System.out.println(fileEntity);
    }
    
    // omitted createOkHttpClientCorrespondedProxy method
    // see Corresponded Proxy
}

python


22:32:58.703 [main] DEBUG feign.Logger - [DownloadApi#download] ---> GET http://www.example.com/documents/2018/pdf/sample.pdf HTTP/1.1
22:32:58.705 [main] DEBUG feign.Logger - [DownloadApi#download] ---> END HTTP (0-byte body)
22:32:58.819 [main] DEBUG feign.Logger - [DownloadApi#download] <--- HTTP/1.1 200 OK (113ms)
22:32:58.820 [main] DEBUG feign.Logger - [DownloadApi#download] accept-ranges: bytes
22:32:58.820 [main] DEBUG feign.Logger - [DownloadApi#download] content-length: 1656363
22:32:58.820 [main] DEBUG feign.Logger - [DownloadApi#download] content-type: application/pdf
22:32:58.820 [main] DEBUG feign.Logger - [DownloadApi#download] date: Thu, 05 Apr 2018 13:32:56 GMT
22:32:58.820 [main] DEBUG feign.Logger - [DownloadApi#download] proxy-connection: Keep-Alive
22:32:58.820 [main] DEBUG feign.Logger - [DownloadApi#download] server: Apache
22:32:58.820 [main] DEBUG feign.Logger - [DownloadApi#download] set-cookie: server-20480-%3Fmntdlb01%3Fsfarm-web_ap=ECBBGDAKFAAA; Path=/
22:32:58.820 [main] DEBUG feign.Logger - [DownloadApi#download] 
22:32:59.678 [main] DEBUG feign.Logger - [DownloadApi#download] Binary data
22:32:59.678 [main] DEBUG feign.Logger - [DownloadApi#download] <--- END HTTP (1656363-byte body)
FileEntity [status=200, headers={accept-ranges=[bytes], content-length=[1656363], content-type=[application/pdf], date=[Thu, 05 Apr 2018 13:32:56 GMT], proxy-connection=[Keep-Alive], server=[Apache], set-cookie=[server-20480-%3Fmntdlb01%3Fsfarm-web_ap=ECBBGDAKFAAA; Path=/]}, reason=OK, file=C:\Users\feign\AppData\Local\Temp\download4121273495791641378.tmp]

6. Schließlich

Dieses Mal habe ich erklärt, wie Sie Ihren eigenen "Decoder" verwenden, um den Dateidownload mit "Feign" zu realisieren. Das nächste Mal möchte ich erklären, wie man das Hochladen von Dateien mit "Feign" realisiert.

Recommended Posts

So erreichen Sie den Dateidownload mit Feign
So erreichen Sie das Hochladen von Dateien mit Feign
So laden Sie Oracle JDK 8 U / min mit Curl herunter
Wie man mit html.erb nummeriert (nummeriert)
So aktualisieren Sie mit activerecord-import
Herunterladen von Dateien (Servlet, HTML, Apache, Tomcat)
So fordern Sie mit jMeter eine CSV-Datei als JSON an
So kehren Sie die Kompilierung der Apk-Datei in Java-Quellcode mit MAC um
[Einfach] So formatieren Sie Ruby erb-Dateien automatisch mit vsCode
So richten Sie einen Proxy mit Authentifizierung in Feign ein
Wie fange ich mit schlank an?
So konvertieren Sie erb-Datei in haml
Implementieren Sie den Dateidownload mit Spring MVC
Wie man mssql-tools mit alpine benutzt
Wie man Paiza Rang D erreicht
[Anfänger] So löschen Sie NO FILE
So starten Sie Camunda mit Docker
So realisieren Sie mit TERASOLUNA 5.x (= Spring MVC) das Hochladen großer Dateien
So öffnen Sie eine Skriptdatei von Ubuntu mit VS-Code
So erzielen Sie mit Rest Template of Spring einen großen Datei-Upload
So beschneiden Sie ein Bild in libGDX
So passen Sie TextPosition mit der iOS-Tastaturerweiterung an
So teilen Sie Dateien mit Docker Toolbox
[Java] Verwendung der File-Klasse
So kompilieren Sie Java mit VsCode & Ant
[Java] Fassen Sie zusammen, wie Sie mit der Methode equals vergleichen können
[Android] Wie man mit dunklen Themen umgeht
So wechseln Sie Miniaturbilder mit JavaScript
[Hinweis] Erste Schritte mit Rspec
API-basierte Steuerung mit cancancan
So aktualisieren Sie verwandte Modelle mit accept_nested_attributes_for
So setzen Sie JAVA_HOME mit dem Appassembler-Maven-Plugin von Maven
So implementieren Sie TextInputLayout mit Validierungsfunktion
So behandeln Sie Anmeldefehler mit devise
So löschen Sie Daten mit einem externen Schlüssel
So testen Sie den privaten Bereich mit JUnit
So überwachen Sie Nginx mit Docker-Compose mit Datadog
Der Umgang mit dem Vorkompilieren von Assets ist fehlgeschlagen.
So teilen Sie eine Spring Boot-Nachrichtendatei
So führen Sie Blazor (C #) mit Docker aus
So erstellen Sie eine Rails 6-Umgebung mit Docker
So starten Sie einen Docker-Container mit einem in einer Batchdatei bereitgestellten Volume
[Java] So testen Sie, ob es in JUnit null ist
Wie man jeden Fall mit Mockito 1x verspottet
[Rails] Lesen der vom Bildschirm hochgeladenen XML-Datei im Hash-Typ
[Ruby] So konvertieren Sie eine CSV-Datei in Yaml (Yml)
Wie man jeden Fall mit PowerMock + Mockito1x verspottet
Verwendung von MyBatis2 (iBatis) mit Spring Boot 1.4 (Spring 4)
So speichern Sie mit einer Eingabe in mehreren Tabellen
So testen Sie Interrupts während Thread.sleep mit JUnit
So sichern Sie von der Datenbank (DB) in die Seeds-Datei
Verwendung des Java-Frameworks mit AWS Lambda! ??
So erstellen Sie mit ActiveHash mehrere Pulldown-Menüs