SpringCloud—Feign多文件上傳解決方案

image

關(guān)于Feign接口單文件上傳务甥,比較簡單窒悔,和普通的 SpringMVC 幾乎是一樣的,對應(yīng)好參數(shù)和配置信息即可。

多文件上傳卻是個頭疼的問題(和自己的水平有關(guān)吧)藤乙。

瀏覽了幾篇博客猜揪,雖然有代碼可以參考,但是并不詳細(xì)坛梁。那么請看下面史上最細(xì)致的Feign多文件上傳總結(jié)(自吹自擂一下)而姐,最細(xì)致談不上,可以讓你真正解決問題划咐。

如果你遇到了下面的這個錯誤提示:

Caused by: org.apache.commons.fileupload.FileUploadException: the request was rejected because no multipart boundary was found

或者

The current request is not a multipart request 

恭喜你來對地方了拴念!

有人說第二個錯誤“就是傳輸?shù)奈募?shù)據(jù)為空了,比較簡單”褐缠,真的簡單么政鼠?當(dāng)你什么都寫了,參數(shù)也有文件了队魏,但是調(diào)用Feign的時(shí)候就是報(bào)這個錯誤公般,這才是最頭疼的問題,明明看著可以器躏,其實(shí)就是不行俐载,鬧心不?

開始解說


環(huán)境版本

Spring-boot版本:

2.2.0.RELEASE

SpringCloud版本:

Hoxton.M3

JDK版本:

1.8

接口提供方

接口提供方不需要特殊處理登失,看一下實(shí)力代碼遏佣,按照示例代碼寫就可以:

    @RequestMapping(value = "/upload/batch" , method = RequestMethod.POST , consumes = MediaType.MULTIPART_FORM_DATA_VALUE )
    public ResponseData upload( @NotNull( message = "文件業(yè)務(wù)類型不能為空") @RequestParam("type") Integer type ,
                                @NotNull( message = "用戶id不能為空") @RequestParam("userId") Long userId ,
                                @RequestParam("images") MultipartFile[] images ) {
        List<UserImageResVO> imageResVos = fileOpService.uploadImages( userId, type, images);
        return ResponseData.success( imageResVos ) ;
    }

注意的地方就是 @RequestMapping上 加上:

consumes = MediaType.MULTIPART_FORM_DATA_VALUE

這里的 文件參數(shù) MultipartFile[] images 注解使用的是:

@RequestParam("images") 

之所以在這里提一下,因?yàn)樵诮涌谙M(fèi)方使用的不是這個(多文件)揽浙。

接口消費(fèi)方

引入依賴
        <dependency>
            <groupId>io.github.openfeign.form</groupId>
            <artifactId>feign-form</artifactId>
            <version>3.8.0</version>
        </dependency>
        <dependency>
            <groupId>io.github.openfeign.form</groupId>
            <artifactId>feign-form-spring</artifactId>
            <version>3.8.0</version>
        </dependency>
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.3</version>
        </dependency>

這是Feign為支持文件上傳提供的依賴状婶,你可以在 這里 選擇不同的版本。

SpringForm編碼器

import feign.RequestTemplate;
import feign.codec.EncodeException;
import feign.codec.Encoder;
import feign.form.MultipartFormContentProcessor;
import feign.form.spring.SpringFormEncoder;
import feign.form.spring.SpringManyMultipartFilesWriter;
import feign.form.spring.SpringSingleMultipartFileWriter;
import org.springframework.web.multipart.MultipartFile;

import java.lang.reflect.Type;
import java.util.Collections;
import java.util.Map;

import static feign.form.ContentType.MULTIPART;

/**
 * @description  處理多個文件上傳 編碼器
 *
 * @author Songxudong
 * @date 2019/11/14 4:25 下午
 */
public class SpringMultipartEncoder extends SpringFormEncoder {
    public SpringMultipartEncoder(Encoder delegate) {
        super(delegate);
        MultipartFormContentProcessor processor = (MultipartFormContentProcessor) getContentProcessor(MULTIPART);
        processor.addWriter(new SpringSingleMultipartFileWriter());
        processor.addWriter(new SpringManyMultipartFilesWriter());
    }

    @Override
    public void encode(Object object, Type bodyType, RequestTemplate template) throws EncodeException {
        if (bodyType != null && bodyType.equals(MultipartFile[].class)) {
            MultipartFile[] file = (MultipartFile[]) object;
            if(file != null) {
                Map data = Collections.singletonMap(file.length == 0 ? "" : file[0].getName(), object);
                super.encode(data, MAP_STRING_WILDCARD, template);
                return;
            }
        }
        super.encode(object, bodyType, template);
    }
}

之所以需要提供這樣一個編碼器馅巷,是因?yàn)樵诔绦騼?nèi)部調(diào)用Feign接口已經(jīng)不是表單環(huán)境了膛虫,需要重新對文件內(nèi)容進(jìn)行編碼操作。
開篇的第一個錯誤和這個就有關(guān)系钓猬,說“boundary(分割線)”找不到稍刀,就是因?yàn)椴皇潜韱翁峤唬韱翁峤坏脑挸ú埽紩嬖诜指罹€(對post請求了解的都應(yīng)該知道)账月。

Feign多文件支持配置
import com.system.consumer.sys.spring.SpringMultipartEncoder;
import feign.codec.Encoder;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.cloud.openfeign.support.SpringEncoder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @description feign-SpringMVC 多文件上傳配置
 *
 * @author Songxudong
 * @date 2019/11/14 1:52 下午
 */
@Configuration
public class FeignMultipartSupportConfig {

    @Autowired
    private ObjectFactory<HttpMessageConverters> messageConverters;

    @Bean
    public Encoder feignEncoder() {
        return new SpringMultipartEncoder(new SpringEncoder(messageConverters));
    }

}

這個配置下面對在注入的Feign接口提供中使用。

在消費(fèi)方對服務(wù)接口進(jìn)行配置
@FeignClient( name = "medical-resource-provider" , configuration = FeignMultipartSupportConfig.class )
public interface IMedicalResourceService {


    /** 文件批量上傳 */
    @PostMapping(value = "/file/upload/batch" , consumes = MediaType.MULTIPART_FORM_DATA_VALUE  )
    ResponseData upload( @RequestParam("type") Integer type , @RequestParam("userId") Long userId ,
                         @RequestPart("images") MultipartFile[] images ) ;
}

【注意:】
1)@RequestMapping中使用 consumes = MediaType.MULTIPART_FORM_DATA_VALUE
2)文件參數(shù)注解使用 @RequestPart澳迫,而不是 @RequestParam
3)將 FeignMultipartSupportConfig 配置加上

對于注意 2)局齿,如果還是使用 @RequestParam 的話,就會出現(xiàn)開篇的第一個錯誤橄登;
consumes = MediaType.MULTIPART_FORM_DATA_VALUE 這個設(shè)置抓歼,如果在調(diào)用接口的定義上不實(shí)用就會出現(xiàn)開篇的第二個錯誤讥此,原因還是因?yàn)椋@里的調(diào)用不是表單環(huán)境了谣妻,需要我們手動告訴接口萄喳,我們的請求是Multipart類型的。在SpringMVC接口中拌禾,我們不需要配置也可以取胎,因?yàn)闀詣訑y帶對應(yīng)的信息。

好啦湃窍,以上就是對Feign多文件上傳問題的解決過程闻蛀,按照以上過程,是沒有問題的您市。
希望可以幫到大家觉痛。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市茵休,隨后出現(xiàn)的幾起案子薪棒,更是在濱河造成了極大的恐慌,老刑警劉巖榕莺,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件俐芯,死亡現(xiàn)場離奇詭異,居然都是意外死亡钉鸯,警方通過查閱死者的電腦和手機(jī)吧史,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來唠雕,“玉大人贸营,你說我怎么就攤上這事⊙艺觯” “怎么了钞脂?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長捕儒。 經(jīng)常有香客問我冰啃,道長,這世上最難降的妖魔是什么刘莹? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任亿笤,我火速辦了婚禮,結(jié)果婚禮上栋猖,老公的妹妹穿的比我還像新娘。我一直安慰自己汪榔,他們只是感情好蒲拉,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布肃拜。 她就那樣靜靜地躺著,像睡著了一般雌团。 火紅的嫁衣襯著肌膚如雪燃领。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天锦援,我揣著相機(jī)與錄音猛蔽,去河邊找鬼。 笑死灵寺,一個胖子當(dāng)著我的面吹牛曼库,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播略板,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼毁枯,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了叮称?” 一聲冷哼從身側(cè)響起种玛,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎瓤檐,沒想到半個月后赂韵,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡挠蛉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年祭示,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片碌秸。...
    茶點(diǎn)故事閱讀 39,919評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡绍移,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出讥电,到底是詐尸還是另有隱情蹂窖,我是刑警寧澤,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布恩敌,位于F島的核電站瞬测,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏纠炮。R本人自食惡果不足惜月趟,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望恢口。 院中可真熱鬧孝宗,春花似錦、人聲如沸耕肩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至婚被,卻和暖如春狡忙,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背址芯。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工灾茁, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人谷炸。 一個月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓北专,卻偏偏與公主長得像,于是被迫代替她去往敵國和親淑廊。 傳聞我的和親對象是個殘疾皇子逗余,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評論 2 354