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.
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
}
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);
}
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);
}
}
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]
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