Dernière fois a expliqué comment réaliser le téléchargement de fichiers avec Feign
.
Cette fois, je voudrais expliquer comment réaliser le téléchargement de fichiers avec Feign
.
J'ai implémenté mon propre Decoder
dans le téléchargement, mais je vais l'utiliser car il existe un module dédié appelé feign-form pour le téléchargement. .. La page officielle de GitHub explique ce qui suit.
This module adds support for encoding application/x-www-form-urlencoded and multipart/form-data forms.
feign-form
est un module séparé, alors ajoutez-le à la dépendance. Pour le pom.xml
de base lors de l'utilisation de Feign
, reportez-vous à Un autre article.
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 -->
Définit l'interface API. Les trois types de types de données d'argument suivants peuvent être utilisés pour la conversion de données de téléchargement de fichiers (sérialisation).
java.io.File
: Définissez le fichier de téléchargement comme File
byte []
: Définit les données du fichier de téléchargement sur byte []
feign.form.FormData
: Définit le fichier de téléchargement avec une classe dédiéeÀ titre d'exemple, j'aimerais utiliser trois types de données cette fois.
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);
}
** Veuillez noter que les trois types ne fonctionnent pas de la même manière. Vérifiez les spécifications du côté du fournisseur d'API (serveur) et utilisez celle qui convient. ** **
Type de données | Content-Disposition:FileMaker | Content-Type: |
---|---|---|
java.io.File |
○: Définir | ◯: Set (jugement automatique depuis l'extension) |
byte[] |
×: non défini | ×: non défini Uniforme application/octet-stream Devient |
feign.form.FormData |
×: non défini | ○: Set (défini explicitement par le programme) |
Le but est de définir une instance de la classe feign.form.FormEncoder
dans la méthode ʻencoder`. D'autres sont identiques à l'utilisation de base de «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();
}
}
}
Le code d'implémentation de feign-form est ouvert au public, vous pouvez donc voir la différence entre les trois types d'opérations.
«FormData» peut être résolu en lui donnant un champ «filename», mais la raison pour laquelle il n'est pas conservé est un mystère. (Bien qu'il conserve contentType
)
5.1. File
https://github.com/OpenFeign/feign-form/blob/master/feign-form/src/main/java/feign/form/multipart/SingleFileWriter.java
SingleFileWriter.Où la méthode writeFileMetadata de la classe parente (AbstractWriter) est appelée en java
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.Méthode java writeFileMetadata
@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);
}
En d'autres termes, dans le cas de "Fichier", ce sera comme suit.
File.getName ()
est défini sur filename
dans Content-Disposition:
Content-Type:
est défini sur ʻURLConnection.guessContentTypeFromName (fileName) `5.2. byte[]
https://github.com/OpenFeign/feign-form/blob/master/feign-form/src/main/java/feign/form/multipart/ByteArrayWriter.java
ByteArrayWriter.Où la méthode writeFileMetadata de la classe parente (AbstractWriter) est appelée en java
writeFileMetadata(output, key, null, null);
En d'autres termes, dans le cas de byte []
, ce sera comme suit.
Content-Disposition:
filename
est défini sur null
Content-Type:
est défini sur ʻapplication / octat-stream`5.3. FormData
https://github.com/OpenFeign/feign-form/blob/master/feign-form/src/main/java/feign/form/multipart/FormDataWriter.java
FormDataWriter.Où la méthode writeFileMetadata de la classe parente (AbstractWriter) est appelée en java
writeFileMetadata(output, key, null, formData.getContentType());
En d'autres termes, dans le cas de «FormData», ce sera comme suit.
Content-Disposition:
filename
est défini sur null
Content-Type:
est défini sur formData.getContentType ()
Cette fois, j'ai expliqué comment réaliser le téléchargement de fichiers avec Feign
. Je pense que c'était plus facile que de télécharger à cause des modules fournis.
Recommended Posts