最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java實(shí)現(xiàn)Fast DFS、服務(wù)器、OSS上傳功能

 更新時(shí)間:2024年04月09日 10:26:23   作者:陳遛狗  
這篇文章主要介紹了Java實(shí)現(xiàn)Fast DFS、服務(wù)器、OSS上傳功能,在實(shí)際的業(yè)務(wù)中,可以根據(jù)客戶(hù)的需求設(shè)置不同的文件上傳需求,支持普通服務(wù)器上傳+分布式上傳(Fast DFS)+云服務(wù)上傳OSS(OSS),需要的朋友可以參考下

支持Fast DFS、服務(wù)器、OSS等上傳方式

介紹

在實(shí)際的業(yè)務(wù)中,可以根據(jù)客戶(hù)的需求設(shè)置不同的文件上傳需求,支持普通服務(wù)器上傳+分布式上傳(Fast DFS)+云服務(wù)上傳OSS(OSS)

軟件架構(gòu)

為了方便演示使用,本項(xiàng)目使用的是前后端不分離的架構(gòu)

前端:Jquery.uploadFile

后端:SpringBoot

前期準(zhǔn)備:FastDFS、OSS(華為)、服務(wù)器

實(shí)現(xiàn)邏輯

通過(guò) application 配置對(duì)上傳文件進(jìn)行一個(gè)自定義配置,從而部署在不同客戶(hù)環(huán)境可以自定義選擇方式。

優(yōu)點(diǎn):

  • 一鍵切換;
  • 支持當(dāng)前主流方式;

缺點(diǎn):

  • 遷移數(shù)據(jù)難度增加:因?yàn)楸硎綟ileID在對(duì)象存儲(chǔ)和服務(wù)器上傳都是生成的UUID,而FastDFS是返回存取ID,當(dāng)需要遷移的時(shí)候,通過(guò)腳本可以快速將FastDFS的數(shù)據(jù)遷移上云,因?yàn)榇鎯?chǔ)ID可以共用。但是對(duì)象存儲(chǔ)和服務(wù)器上傳的UUID無(wú)法被FastDFS使用,增加遷移成本

核心代碼

package com.example.file.util;
import com.example.file.common.ResultBean;
import com.github.tobato.fastdfs.domain.StorePath;
import com.github.tobato.fastdfs.proto.storage.DownloadByteArray;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.obs.services.ObsClient;
import com.obs.services.exception.ObsException;
import com.obs.services.model.DeleteObjectRequest;
import com.obs.services.model.GetObjectRequest;
import com.obs.services.model.ObsObject;
import com.obs.services.model.PutObjectResult;
import io.micrometer.common.util.StringUtils;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.util.Objects;
import java.util.UUID;
@Slf4j
public class FileUtil {
    /**
     *
     * @param file 文件
     * @param uploadFlag 標(biāo)識(shí)
     * @param uploadPath 上傳路徑
     * @param endPoint 域名
     * @param ak    ak
     * @param sk sk
     * @param bucketName 桶名字
     * @return fileId 用于下載
     */
    public static ResultBean uploadFile(MultipartFile file, String uploadFlag, String uploadPath,
                                        FastFileStorageClient fastFileStorageClient,
                                        String endPoint, String ak, String sk,
                                        String bucketName) {
        if (StringUtils.isBlank(uploadFlag)){
            ResultBean.error("uploadFlag is null");
        }
        switch (uploadFlag){
            case "fastDFS":
                return uploadFileByFastDFS(file,fastFileStorageClient);
            case "huaweiOOS":
                return uploadFileByHuaweiObject(file, endPoint, ak, ak, bucketName);
            case "server":
            default:
                return uploadFileByOrigin(file,uploadPath);
        }}
    /**
     * 上傳文件fastDFS
     * @param file 文件名
     * @return
     */
    private static ResultBean uploadFileByFastDFS(MultipartFile file,FastFileStorageClient fastFileStorageClient){
        Long size=file.getSize();
        String fileName=file.getOriginalFilename();
        String extName=fileName.substring(fileName.lastIndexOf(".")+1);
        InputStream inputStream=null;
        try {
            inputStream=file.getInputStream();
            //1-上傳的文件流 2-文件的大小 3-文件的后綴 4-可以不管他
            StorePath storePath=fastFileStorageClient.uploadFile(inputStream,size,extName,null);
            log.info("[uploadFileByFastDFS][FullPath]"+storePath.getFullPath());
            return ResultBean.success(storePath.getPath());
        }catch (Exception e){
            log.info("[ERROR][uploadFileByFastDFS]"+e.getMessage());
            return ResultBean.error(e.getMessage());
        }finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    /**
     * 對(duì)象存儲(chǔ)上傳
     * @param file 文件名
     * @return
     */
    private static ResultBean uploadFileByHuaweiObject(MultipartFile file, String huaweiEndPoint,String huaweiobsAk,String huaweiobsSk,
                                                   String bucketName){
        String fileName = file.getOriginalFilename();
        fileName = renameToUUID(fileName);
        InputStream inputStream=null;
        try {
            inputStream=file.getInputStream();
            // 創(chuàng)建ObsClient實(shí)例
            ObsClient obsClient = new ObsClient(huaweiobsAk, huaweiobsSk, huaweiEndPoint);
            PutObjectResult result = obsClient.putObject(bucketName, fileName, inputStream);
            obsClient.close();
            return ResultBean.success(fileName);
        }catch (ObsException e){
            log.info("[ERROR][uploadFileByHuaweiObject]"+e.getErrorMessage());
            return ResultBean.error(e.getErrorMessage());
        }catch (Exception e){
            log.info("[ERROR][uploadFileByHuaweiObject]"+e.getMessage());
            return ResultBean.error(e.getMessage());
        }finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    /**
     * 上傳文件原本方法
     * @param file 文件名
     * @return
     */
    private static ResultBean uploadFileByOrigin(MultipartFile file,String uploadPath){
        String fileName = file.getOriginalFilename();
        fileName = renameToUUID(fileName);
        File targetFile = new File(uploadPath);
        if (!targetFile.exists()) {
            targetFile.mkdirs();
        }
        FileOutputStream out = null;
        try {
            out = new FileOutputStream(uploadPath + fileName);
            out.write(file.getBytes());
        } catch (IOException e) {
            log.info("[ERROR][uploadFileByOrigin]"+e.getMessage());
            return ResultBean.error(e.getMessage());
        }finally {
            try {
                out.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return ResultBean.success(fileName);
    }
    /**
     * 下載
     * @return
     */
    public static byte[] downloadFile(String fileId,String uploadFlag,String uploadPath
            ,FastFileStorageClient fastFileStorageClient, String group,
                                      String endPoint,String ak,String sk,
                                      String bucketName) {
        byte[] result=null;
        switch (uploadFlag){
            case "fastDFS":
                result =downloadFileByFastDFS(fileId,fastFileStorageClient,group);
                break;
            case "huaweiOOS":
                result =downloadFileByHuaweiObject(fileId, endPoint, ak, sk, bucketName);
                break;
            case "server":
            default:
                String path2 = uploadPath + fileId;
                path2 = path2.replace("http://", "/");
                result=downloadFileByOrigin(path2);
                break;
        }
        return result;
    }
    /**
     * 下載文件fastDFS
     * @param fileId 文件名
     * @return
     */
    private static byte[] downloadFileByFastDFS(String fileId,FastFileStorageClient fastFileStorageClient,
                                                String group){
        DownloadByteArray callback=new DownloadByteArray();
        byte[] group1s=null;
        try {
            group1s = fastFileStorageClient.downloadFile(group, fileId, callback);
        }catch (Exception e){
            log.info("[ERROR][downloadFileByFastDFS]"+e.getMessage());
        }
        return group1s;
    }
    /**
     * 下載文件對(duì)象存儲(chǔ)
     * @param fileId 文件名
     * @return
     */
    private static byte[] downloadFileByHuaweiObject(String fileId, String huaweiEndPoint,String huaweiobsAk,String huaweiobsSk,
                                                     String bucketName){
        byte[] bytes =null;
        try {
            // 創(chuàng)建ObsClient實(shí)例
            ObsClient obsClient = new ObsClient(huaweiobsAk, huaweiobsSk, huaweiEndPoint);
            // 構(gòu)造GetObjectRequest請(qǐng)求
            GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, fileId);
            // 執(zhí)行下載操作
            ObsObject obsObject = obsClient.getObject(getObjectRequest);
            bytes = inputStreamToByteArray(obsObject.getObjectContent());
            // 關(guān)閉OBS客戶(hù)端
            obsClient.close();
            return bytes;
        }catch (ObsException e){
            log.info("[ERROR][downloadFileByHuaweiObject]"+e.getErrorMessage());
        }catch (Exception e) {
            log.info("[ERROR][downloadFileByHuaweiObject]"+e.getMessage());
        }
        return bytes;
    }
    /**
     *
     * @param input
     * @return
     * @throws IOException
     */
    private static byte[] inputStreamToByteArray(InputStream input) throws IOException {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        byte[] buffer = new byte[4096];
        int n = 0;
        while (-1 != (n = input.read(buffer))) {
            output.write(buffer, 0, n);
        }
        return output.toByteArray();
    }
    /**
     * 下載文件
     * @param fileId 文件名
     * @return
     */
    private static byte[] downloadFileByOrigin(String fileId){
        File file  =new File(fileId);
        InputStream inputStream=null;
        byte[] buff = new byte[1024];
        byte[] result=null;
        BufferedInputStream bis = null;
        ByteArrayOutputStream os = null;
        try {
            os=new ByteArrayOutputStream();
            bis = new BufferedInputStream(new FileInputStream(file));
            int i = bis.read(buff);
            while (i != -1) {
                os.write(buff, 0, buff.length);
                i = bis.read(buff);
            }
            result=os.toByteArray();
            os.flush();
        } catch (Exception e) {
            log.info("[ERROR][downloadFile]"+e.getMessage());
        }finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return result;
    }
    /**
     * 刪除文件
     * @param fileId 文件ID
     * @return 刪除失敗返回-1,否則返回0
     */
    public static boolean deleteFile(String fileId,String fastDFSFlag,FastFileStorageClient fastFileStorageClient,
                                     String group,String uploadPath) {
        boolean result=false;
        if (StringUtils.isNotBlank(fastDFSFlag)&&
                fastDFSFlag.trim().equalsIgnoreCase("true")){
            result =deleteFileByFastDFS(fileId,fastFileStorageClient,group);
        }else {
            String path2 = uploadPath + fileId;
            path2 = path2.replace("http://", "/");
            result=deleteByOrigin(path2);
        }
        return result;
    }
    private static boolean deleteByOrigin(String fileName) {
        File file = new File(fileName);
        // 如果文件路徑所對(duì)應(yīng)的文件存在,并且是一個(gè)文件,則直接刪除
        if (file.exists() && file.isFile()) {
            if (file.delete()) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }
    private static boolean deleteFileByFastDFS(String fileId,FastFileStorageClient fastFileStorageClient,
                                               String group) {
        try {
            String groupFieId=group+"/"+fileId;
            StorePath storePath = StorePath.praseFromUrl(groupFieId);
            fastFileStorageClient.deleteFile(storePath.getGroup(), storePath.getPath());
        } catch (Exception e) {
            log.info("[ERROR][deleteFileByFastDFS]"+e.getMessage());
            return false;
        }
        return true;
    }
    /**
     * 生成fileId
     * @param fileName
     * @return
     */
    private static String renameToUUID(String fileName) {
        return UUID.randomUUID() + "." + fileName.substring(fileName.lastIndexOf(".") + 1);
    }
    /**
     * 刪除文件對(duì)象存儲(chǔ)
     * @param fileId 文件名
     * @return
     */
    private static boolean deleteFileByHuaweiObject(String fileId, String huaweiEndPoint,String huaweiobsAk,String huaweiobsSk,
                                                    String bucketName){
        try {
            // 創(chuàng)建ObsClient實(shí)例
            ObsClient obsClient = new ObsClient(huaweiobsAk, huaweiobsSk, huaweiEndPoint);
            // 構(gòu)造GetObjectRequest請(qǐng)求
            DeleteObjectRequest getObjectRequest = new DeleteObjectRequest(bucketName, fileId);
            // 執(zhí)行刪除操作
            obsClient.deleteObject(getObjectRequest);
            // 關(guān)閉OBS客戶(hù)端
            obsClient.close();
        }catch (ObsException e){
            log.info("[ERROR][deleteFileByHuaweiObject]"+e.getErrorMessage());
        }catch (Exception e) {
            log.info("[ERROR][downloadFileByHuaweiObject]"+e.getMessage());
        }
        return true;
    }
    /**
     * 文件數(shù)據(jù)輸出(image)
     * @param fileId
     * @param bytes
     * @param res
     */
    public static void fileDataOut(String fileId, byte[] bytes, HttpServletResponse res){
        String[] prefixArray = fileId.split("\\.");
        String prefix=prefixArray[1];
        File file  =new File(fileId);
        res.reset();
        res.setCharacterEncoding("utf-8");
//        res.setHeader("content-type", "");
        res.addHeader("Content-Length", "" + bytes.length);
        if(prefix.equals("svg"))
            prefix ="svg+xml";
        res.setContentType("image/"+prefix);
        res.setHeader("Accept-Ranges","bytes");
        OutputStream os = null;
        try {
//            os = res.getOutputStream();
//            os.write(bytes);
//            os.flush();
            res.getOutputStream().write(bytes);
        } catch (IOException e) {
            System.out.println("not find img..");
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

參考資料

假設(shè)個(gè)人實(shí)戰(zhàn)使用可以采用docker快速安裝,但是未安裝過(guò)FastDFS建議普通安裝部署,了解一下tracker和storage的使用,以及部署搭建集群。

FastDFS普通安裝部署:https://www.cnblogs.com/chenliugou/p/15322389.html

FasdDFS docker安裝部署:https://blog.csdn.net/weixin_44621343/article/details/117825755?utm_medium=distribute.pc_relevant.none-task-blog-2defaultbaidujs_baidulandingword~default-0-117825755-blog-127896984.235v43pc_blog_bottom_relevance_base6&spm=1001.2101.3001.4242.1&utm_relevant_index=3

OpenFeign和FastDFS的類(lèi)沖突:https://www.cnblogs.com/chenliugou/p/18113183

Gitee地址:https://gitee.com/chen-liugou/file/new/master?readme=true

到此這篇關(guān)于Java實(shí)現(xiàn)Fast DFS、服務(wù)器、OSS上傳功能的文章就介紹到這了,更多相關(guān)java Fast DFS上傳內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java常見(jiàn)的字符串拼接方式總結(jié)

    java常見(jiàn)的字符串拼接方式總結(jié)

    這篇文章主要為大家詳細(xì)介紹了java中常見(jiàn)的字符串拼接方式,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-09-09
  • 詳解Spring Boot中初始化資源的幾種方式

    詳解Spring Boot中初始化資源的幾種方式

    這篇文章主要介紹了詳解Spring Boot中初始化資源的幾種方式,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-08-08
  • java實(shí)現(xiàn)Redisson的基本使用

    java實(shí)現(xiàn)Redisson的基本使用

    Redisson是一個(gè)在Redis的基礎(chǔ)上實(shí)現(xiàn)的Java駐內(nèi)存數(shù)據(jù)網(wǎng)格客戶(hù)端,本文主要介紹了java實(shí)現(xiàn)Redisson的基本使用,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-12-12
  • SpringBoot使用jsr303校驗(yàn)的實(shí)現(xiàn)

    SpringBoot使用jsr303校驗(yàn)的實(shí)現(xiàn)

    這篇文章主要介紹了SpringBoot使用jsr303校驗(yàn)的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • Java過(guò)濾所有特殊字符的案例

    Java過(guò)濾所有特殊字符的案例

    這篇文章主要介紹了Java過(guò)濾所有特殊字符的相關(guān)資料,包括java中清理所有特殊字符及java正則過(guò)濾特殊字符的方法,感興趣的朋友跟隨小編一起看看吧
    2024-02-02
  • Java的Struts框架中配置國(guó)際化的資源存儲(chǔ)的要點(diǎn)解析

    Java的Struts框架中配置國(guó)際化的資源存儲(chǔ)的要點(diǎn)解析

    這篇文章主要介紹了Java的Struts框架中配置國(guó)際化的資源存儲(chǔ)的要點(diǎn)解析,針對(duì)用戶(hù)所使用的語(yǔ)言來(lái)配置資源文件,需要的朋友可以參考下
    2016-04-04
  • 為什么阿里禁止使用Executors去創(chuàng)建線(xiàn)程池

    為什么阿里禁止使用Executors去創(chuàng)建線(xiàn)程池

    文章主要介紹了阿里巴巴禁止使用Executors.newFixedThreadPool()方法創(chuàng)建線(xiàn)程池的原因,指出了該方法的無(wú)界工作隊(duì)列帶來(lái)的隱患,感興趣的朋友跟隨小編一起看看吧
    2025-12-12
  • Mybatis之動(dòng)態(tài)SQL使用小結(jié)(全網(wǎng)最新)

    Mybatis之動(dòng)態(tài)SQL使用小結(jié)(全網(wǎng)最新)

    MyBatis令人喜歡的一大特性就是動(dòng)態(tài)SQL,?在使用JDBC的過(guò)程中,?根據(jù)條件進(jìn)行SQL的拼接是很麻煩且很容易出錯(cuò)的,MyBatis通過(guò)OGNL來(lái)進(jìn)行動(dòng)態(tài)SQL的使用解決了這個(gè)麻煩,對(duì)Mybatis動(dòng)態(tài)SQL相關(guān)知識(shí)感興趣的朋友跟隨小編一起看看吧
    2024-05-05
  • 關(guān)于String.format使用詳解

    關(guān)于String.format使用詳解

    文章介紹了Java中String.format的使用,通過(guò)格式說(shuō)明符實(shí)現(xiàn)簡(jiǎn)潔、可維護(hù)的字符串拼接,適用于日志生成、數(shù)據(jù)格式化、編號(hào)處理等場(chǎng)景,支持靈活的格式控制與null值處理,顯著提升代碼可讀性和靈活性
    2025-08-08
  • Java File類(lèi)的簡(jiǎn)單使用教程(創(chuàng)建、刪除、遍歷與判斷是否存在等)

    Java File類(lèi)的簡(jiǎn)單使用教程(創(chuàng)建、刪除、遍歷與判斷是否存在等)

    這篇文章主要給大家介紹了關(guān)于Java File類(lèi)的簡(jiǎn)單使用(創(chuàng)建、刪除、遍歷與判斷是否存在等)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12

最新評(píng)論

河曲县| 九寨沟县| 昌邑市| 柳河县| 镇远县| 遂平县| 吉安市| 康乐县| 始兴县| 北流市| 太康县| 金昌市| 湖南省| 汝阳县| 林甸县| 田林县| 阳原县| 博罗县| 定西市| 福鼎市| 大宁县| 南城县| 南溪县| 南涧| 沙湾县| 武汉市| 茌平县| 吉林省| 和田市| 河曲县| 远安县| 龙川县| 安溪县| 宣武区| 木兰县| 仪陇县| 杨浦区| 榆中县| 宜丰县| 沙雅县| 五指山市|