spring cloud feign 文件上傳和文件下載

来源:https://www.cnblogs.com/liran123/archive/2019/02/24/10428459.html
-Advertisement-
Play Games

文件上傳參考文檔:http://blog.didispace.com/spring-cloud-starter-dalston-2-4/ 文件下載參考文檔:https://blog.csdn.net/aaronsimon/article/details/82710979 我的spring boot ...


文件上傳參考文檔:http://blog.didispace.com/spring-cloud-starter-dalston-2-4/

文件下載參考文檔:https://blog.csdn.net/aaronsimon/article/details/82710979

我的spring boot ,spring cloud 版本是:

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.1.RELEASE</version>
<relativePath/>
</parent>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.M9</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

 

服務調用方 feign文件下載需要配置的config:

import feign.codec.Encoder;
import feign.form.spring.SpringFormEncoder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FeignMultipartSupportConfig {
    @Bean
    public Encoder feignFormEncoder() {
        return new SpringFormEncoder();
    }
}  

 

對應的feign pom.xml需要引入

     <!--feign upload file-->
        <dependency>
            <groupId>io.github.openfeign.form</groupId>
            <artifactId>feign-form</artifactId>
            <version>3.0.3</version>
        </dependency>
        <dependency>
            <groupId>io.github.openfeign.form</groupId>
            <artifactId>feign-form-spring</artifactId>
            <version>3.0.3</version>
        </dependency>
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.3</version>
        </dependency>  

 

服務調用方controller:

import com.yft.common.annotation.Log;
import com.yft.sys.modules.test.fileclient.FileTestClient;
import feign.Response;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;

/**
 * feign 熔斷器示例
 *
 * @author oKong
 */
@RestController
@Slf4j
public class FileController {

    @Autowired
    FileTestClient fileTestClient;

    @Log("文件上傳測試")
    @PostMapping("/upload")
    public Object upload(MultipartFile file) {
        log.info("使用feign調用服務,文件上傳");
        return fileTestClient.upload(file);
    }

    @Log("文件下載測試")
    @RequestMapping(value = "/download", method = RequestMethod.GET)
    public ResponseEntity<byte[]> downFile() {
        log.info("使用feign調用服務 文件下載");

        ResponseEntity<byte[]> result = null;
        InputStream inputStream = null;
        try {
            // feign文件下載
            Response response = fileTestClient.download();
            Response.Body body = response.body();
            inputStream = body.asInputStream();
            byte[] b = new byte[inputStream.available()];
            inputStream.read(b);
            HttpHeaders heads = new HttpHeaders();
            heads.add(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=lr.xls");
            heads.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);

            result = new ResponseEntity<byte[]>(b, heads, HttpStatus.OK);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return result;
    }
}

服務調用方feign client寫法(文件上傳主要是上面第一步配置,文件下載主要是返回的feign 的response):

import com.yft.sys.modules.ClientUrl;
import com.yft.sys.modules.test.fileclient.impl.FileTestClientFallbackFactory;
import feign.Response;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.multipart.MultipartFile;

/**
 * @author lr
 */
@FeignClient(name = ClientUrl.SYSTEM_NAME, fallbackFactory = FileTestClientFallbackFactory.class)
@Component
public interface FileTestClient {

    /**
     * 上傳文件測試
     *
     * @return
     */
    @PostMapping(value = ClientUrl.PRE_REQUEST_RUL + "/file/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    Object upload(MultipartFile file);

    /**
     * 下載文件測試
     */
    @RequestMapping(value = ClientUrl.PRE_REQUEST_RUL + "/file/download", method = RequestMethod.GET)
    Response download();

}

服務調用方 feign client 異常類:

import com.yft.sys.modules.test.fileclient.FileTestClient;
import feign.Response;
import feign.hystrix.FallbackFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

/**
 * @author lr
 */
@Slf4j
@Component
public class FileTestClientFallbackFactory implements FallbackFactory<FileTestClient> {
    @Override
    public FileTestClient create(Throwable cause) {

        return new FileTestClient() {
            @Override
            public Object upload(MultipartFile file) {
                log.error("fallback; file upload reason was: " + cause.getMessage());
                return null;
            }

            @Override
            public Response download() {
                log.error("fallback; file download reason was: " + cause.getMessage());
                return null;
            }
        };
    }
}

 

服務提供方呢與原來寫法一樣,沒差別

   @PostMapping(value = "upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public R upload(MultipartFile file) {
        try {
            String fileName = file.getOriginalFilename();
            fileName = FileUtils.renameToUUID(fileName);
            String resPath = FileUtils.saveFile(file.getBytes(), filePath, fileName);
//            fileService.save(new FileDO() {{
//                setCreateDate(new Date());
//                setUrl("http://localhost:8004" + filePre + "/"+resPath);
//                setType(1);
//            }});
            return R.ok().put("resPath", resPath);
        } catch (IOException e) {
            e.printStackTrace();
            return R.error("文件上傳失敗");
        }
    }

    @GetMapping("/download")
    public void downLoad(HttpServletResponse response) throws IOException {
    //這裡示意下載excel文件,自己隨便下載點東西
     /*我們先定義一個嵌套的List,List的元素也是一個List,內層的一個List代表一行數據, 每行都有4個單元格,最終list對象代表多行數據。*/ List<String> row1 = CollUtil.newArrayList("aa", "bb", "cc", "dd"); List<String> row2 = CollUtil.newArrayList("aa1", "bb1", "cc1", "dd1"); List<String> row3 = CollUtil.newArrayList("aa2", "bb2", "cc2", "dd2"); List<String> row4 = CollUtil.newArrayList("aa3", "bb3", "cc3", "dd3"); List<String> row5 = CollUtil.newArrayList("aa4", "bb4", "cc4", "dd4"); List<List<String>> rows = CollUtil.newArrayList(row1, row2, row3, row4, row5); // 然後我們創建ExcelWriter對象後寫出數據: // 通過工具類創建writer,預設創建xls格式 ExcelWriter writer = ExcelUtil.getWriter(); // 一次性寫出內容,使用預設樣式 writer.write(rows); //out為OutputStream,需要寫出到的目標流 //response為HttpServletResponse對象 response.setContentType("application/vnd.ms-excel;charset=utf-8"); //test.xls是彈出下載對話框的文件名,不能為中文,中文請自行編碼 response.setHeader("Content-Disposition", "attachment;filename=test.xls"); ServletOutputStream out = response.getOutputStream(); writer.flush(out); // 關閉writer,釋放記憶體 writer.close(); }

 

文件上傳配置yml

#上傳文件配置
app:
filePath: D:/uploaded_files/
pre: /files
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Value("${app.filePath}")
String filePath;

@Value("${app.pre}")
String pre;

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler(pre + "/**").addResourceLocations("file:///" + filePath);
}

}

 

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.UUID;

public class FileUtils {
    public static String saveFile(byte[] file, String filePath, String fileName) {
        int random = (int) (Math.random() * 100 + 1);
        int random1 = (int) (Math.random() * 100 + 1);
        filePath = filePath + random + File.separator + random1 + File.separator;
        File targetFile = new File(filePath);
        if (!targetFile.exists()) {
            targetFile.mkdirs();
        }
        FileOutputStream fileOutputStream = null;
        try {
            fileOutputStream = new FileOutputStream(filePath + fileName);
            FileChannel fileChannel = fileOutputStream.getChannel();
            ByteBuffer buf = ByteBuffer.wrap(file);
            while (fileChannel.write(buf) != 0) {
            }
        } catch (Exception e) {

        } finally {
            if (fileOutputStream != null) {
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        //url
        return random + "/" + random1 + "/" + fileName;
    }

    public static boolean deleteFile(String fileName) {
        File file = new File(fileName);
        // 如果文件路徑所對應的文件存在,並且是一個文件,則直接刪除
        if (file.exists() && file.isFile()) {
            if (file.delete()) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }

    public static String renameToUUID(String fileName) {
        return UUID.randomUUID() + "." + fileName.substring(fileName.lastIndexOf(".") + 1);
    }
}

   


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • interpreter 解釋器 authentication 認證 Location 定位 invalid 無效的 ...
  • 今天總算開學了,當了班長就是麻煩,明明自己沒買書卻要帶著一波人去領書,那能怎麼辦呢,只能說我善人心腸哈哈哈,不過我腦子裡突然浮起一個念頭,大二還要不要繼續當這個班委呢,既然已經體驗過就可以適當放下了吧,用心在自己的研究上。晚上級會開完也就八點多了,開始打打題,今天在HDU杭電的ACM集訓題看到一個奇 ...
  • powershell腳本站點的搭建 一、Powersploit Powersploit是一款基於powershell的後滲透(Post-Exploitation)框架,集成大量滲透相關模塊和功能。 下載powersploit github地址: https://github.com/mattifes ...
  • 以各個城市的天氣為例, 先準備下麵的數據: 印度天氣的相關信息: 美國天氣的相關信息: 用 concat 組合上面兩個 dataframe: 輸出: 上面的輸出最左邊的序列號是重覆的, 原因是數據分別來自兩個 dataframe 的索引值, 可以通過忽略原本的索引來做改變: 輸出: 下麵再介紹另一種 ...
  • 根據inspect模塊官文文檔中關於函數參數類型的相關說明,python函數參數共有五種類型,按順序分別為:POSITIONAL_ONLY、POSITIONAL_OR_KEYWORD、VAR_POSITIONAL、KEYWORD_ONLY、VAR_KEYWORD。如圖: POSITIONAL_ONL ...
  • mybatis config.xml里標簽可以放置多個environment,這裡可以切換test和develop數據源 databaseIdProvider提供多種資料庫,在xml映射文件里選擇databaseId即可使用對應的資料庫 Oracle的自增是使用Sequence實現的,若要獲取插入數 ...
  • 引言 - 沒得寫 最近工作上需要處理事情很多(接手, 維穩, 危機), 還有深入讀書計劃也提上了日程. 為了每月水經驗, 這裡帶大家寫個 C 的多值返回吧 : ) 後記 - 人生自古誰無死 老兵賣冰 - https://music.163.com/#/song?id=117573 歷史的長河中, 有 ...
  • 新聞 "Fable 2.2發佈,支持匿名記錄" "Paket提升還原時間" "Microsoft.Jupyter.Core預覽" ".NET Framework 4.8早期可訪問編譯版本3745" 博客 "使用SAFE技術棧進行服務端渲染" "CNTK 102.5:在F 的Jupyter里使用Gra ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...