Letztes Mal erklärte, wie man mit Feign
einen Dateidownload erreicht.
Dieses Mal möchte ich erklären, wie man das Hochladen von Dateien mit Feign
realisiert.
Ich habe meinen eigenen "Decoder" im Download implementiert, aber ich werde diesen verwenden, da es ein dediziertes Modul namens feign-form zum Hochladen gibt. .. Die offizielle Seite von GitHub erklärt Folgendes.
This module adds support for encoding application/x-www-form-urlencoded and multipart/form-data forms.
feign-form
ist ein separates Modul, also füge es der Abhängigkeit hinzu. Informationen zur grundlegenden pom.xml
bei Verwendung von Feign
finden Sie unter Ein anderer Artikel.
pom.xml
<!-- add feign-form for multipart : start -->
<dependency>
<groupId>io.github.openfeign.form</groupId>
<artifactId>feign-form</artifactId>
<version>3.3.0</version>
</dependency>
<!-- add feign-form for multipart : end -->
Definiert die API-Schnittstelle. Es gibt die folgenden drei Arten von Argumentdatentypen, die für die Konvertierung von Datei-Upload-Daten (Serialisierung) verwendet werden können.
java.io.File
: Setzt die Upload-Datei auf File
byte []
: Legen Sie die Dateidaten der Upload-Datei als byte []
festfeign.form.FormData
: Legt die Upload-Datei mit einer dedizierten Klasse festAls Beispiel möchte ich diesmal drei Arten von Daten verwenden.
UploadApi.java
package com.example.feign.demo.upload;
import java.io.File;
import feign.Headers;
import feign.Param;
import feign.RequestLine;
import feign.form.FormData;
public interface UploadApi {
@RequestLine("POST /data/upload")
@Headers("Content-Type: multipart/form-data")
String upload(@Param("remarks") String remarks, @Param("uploadFile") File uploadFile);
@RequestLine("POST /data/upload")
@Headers("Content-Type: multipart/form-data")
String upload(@Param("remarks") String remarks, @Param("uploadFile") byte[] uploadFile);
@RequestLine("POST /data/upload")
@Headers("Content-Type: multipart/form-data")
String upload(@Param("remarks") String remarks, @Param("uploadFile") FormData uploadFile);
}
** Bitte beachten Sie, dass nicht alle drei Typen gleich funktionieren. Überprüfen Sie die Spezifikationen auf der Seite des API-Anbieters (Servers) und verwenden Sie die entsprechende. ** ** **
Datentyp | Content-Disposition:FileMaker | Content-Type: |
---|---|---|
java.io.File |
○: Einstellen | ◯: Set (automatische Beurteilung durch Verlängerung) |
byte[] |
×: Nicht eingestellt | ×: Nicht eingestellt Uniform application/octet-stream Wird |
feign.form.FormData |
×: Nicht eingestellt | ○: Set (explizit vom Programm gesetzt) |
Es geht darum, eine Instanz der Klasse "feign.form.FormEncoder" in der Methode "encoder" festzulegen. Andere sind die gleichen wie die Grundverwendung von "Feign".
DownloadDemo.java
package com.example.feign.demo.upload;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import feign.Feign;
import feign.Logger;
import feign.form.FormData;
import feign.form.FormEncoder;
import feign.jackson.JacksonEncoder;
import feign.okhttp.OkHttpClient;
import feign.slf4j.Slf4jLogger;
public class UploadDemo {
public static void main(String[] args) {
// 1. create instance of api interface with feign
UploadApi uploadApi = Feign.builder()
.client(new OkHttpClient())
// use FormEncoder with JacksonEncoder
.encoder(new FormEncoder(new JacksonEncoder()))
// .encoder(new FormEncoder())
.logger(new Slf4jLogger())
.logLevel(Logger.Level.FULL)
.target(UploadApi.class, "http://localhost:3000");
// 2. call api
// File
File uploadFile = new File("C:/tmp/test.png ");
String remarks = "I send a image file.";
String result = uploadApi.upload(remarks, uploadFile);
System.out.println(result);
try (FileInputStream iStream = new FileInputStream(uploadFile);) {
// byte[]
byte[] uploadFileByte = new byte[(int) uploadFile.length()];
iStream.read(uploadFileByte);
String result2 = uploadApi.upload(remarks, uploadFileByte);
System.out.println(result2);
// FormData
FormData formData = new FormData("image/png", uploadFileByte);
String result3 = uploadApi.upload(remarks, formData);
System.out.println(result3);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Der Implementierungscode von feign-form ist öffentlich zugänglich, sodass Sie den Unterschied zwischen den drei Arten von Vorgängen erkennen können.
FormData
kann gelöst werden, indem man ihm ein Feld mit Dateiname
gibt, aber es ist ein Rätsel, warum es nicht beibehalten wird. (Obwohl es "contentType" behält)
5.1. File
https://github.com/OpenFeign/feign-form/blob/master/feign-form/src/main/java/feign/form/multipart/SingleFileWriter.java
SingleFileWriter.Wobei die writeFileMetadata-Methode der übergeordneten Klasse (AbstractWriter) in Java aufgerufen wird
writeFileMetadata(output, key, file.getName(), null);
https://github.com/OpenFeign/feign-form/blob/master/feign-form/src/main/java/feign/form/multipart/AbstractWriter.java
AbstractWriter.Java WriteFileMetadata-Methode
@SneakyThrows
protected void writeFileMetadata (Output output, String name, String fileName, String contentType) {
val contentDesposition = new StringBuilder()
.append("Content-Disposition: form-data; name=\"").append(name).append("\"; ")
.append("filename=\"").append(fileName).append("\"")
.toString();
String fileContentType = contentType;
if (fileContentType == null) {
if (fileName != null) {
fileContentType = URLConnection.guessContentTypeFromName(fileName);
}
if (fileContentType == null) {
fileContentType = "application/octet-stream";
}
}
val string = new StringBuilder()
.append(contentDesposition).append(CRLF)
.append("Content-Type: ").append(fileContentType).append(CRLF)
.append("Content-Transfer-Encoding: binary").append(CRLF)
.append(CRLF)
.toString();
output.write(string);
}
Mit anderen Worten, im Fall von "Datei" ist dies wie folgt.
File.getName ()
wird in Dateiname
vonContent-Disposition:
gesetztContent-Type:
ist auf URLConnection.guessContentTypeFromName (fileName)
gesetzt5.2. byte[]
https://github.com/OpenFeign/feign-form/blob/master/feign-form/src/main/java/feign/form/multipart/ByteArrayWriter.java
ByteArrayWriter.Wobei die writeFileMetadata-Methode der übergeordneten Klasse (AbstractWriter) in Java aufgerufen wird
writeFileMetadata(output, key, null, null);
Mit anderen Worten, im Fall von "byte []" ist es wie folgt.
Content-Disposition:
Dateiname
wird auf null
gesetztContent-Type:
ist auf application / octat-stream
gesetzt5.3. FormData
https://github.com/OpenFeign/feign-form/blob/master/feign-form/src/main/java/feign/form/multipart/FormDataWriter.java
FormDataWriter.Wobei die writeFileMetadata-Methode der übergeordneten Klasse (AbstractWriter) in Java aufgerufen wird
writeFileMetadata(output, key, null, formData.getContentType());
Mit anderen Worten, im Fall von "FormData" ist dies wie folgt.
Content-Disposition:
Dateiname
wird auf null
gesetztContent-Type:
ist auf formData.getContentType ()
gesetztDieses Mal erklärte ich, wie man das Hochladen von Dateien mit "Feign" realisiert. Ich denke, es war einfacher als das Herunterladen aufgrund der bereitgestellten Module.
Recommended Posts