欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

springboot實(shí)現(xiàn)圖片上傳與下載功能

 更新時(shí)間:2024年12月26日 08:58:15   作者:會(huì)說法語的豬  
這篇文章主要為大家詳細(xì)介紹了后端spring項(xiàng)目經(jīng)常要做的功能,實(shí)現(xiàn)圖片上傳和下載,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

寫一下后端spring項(xiàng)目經(jīng)常要做的功能,實(shí)現(xiàn)圖片上傳和下載,這里也把前端代碼附上了??赡芩闶莻€(gè)簡(jiǎn)單版的,我這里圖片上傳都存在當(dāng)前項(xiàng)目的根目錄resource下了。

這里包含了,上傳文件、下載文件(下載文件流、獲取base64),service中還有個(gè)文件流轉(zhuǎn)base64的工具方法。

下面是后端代碼

Controller

package com.wft.controller;
 
import com.wft.model.ActionResult;
import com.wft.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
 
import java.io.*;
 
@RestController
@RequestMapping("/file")
public class TestController {
 
    @Autowired
    TestService testService;
 
    /**
     * 文件上傳
     * @param file
     * @return
     * @throws IOException
     */
    @PostMapping("/upload")
    public ActionResult uploadTest(@RequestParam("file") MultipartFile file) throws IOException {
        return testService.upload(file);
    }
 
    /**
     * 文件下載
     * @param name
     * @return
     * @throws FileNotFoundException
     */
    @GetMapping("/download/{name}")
    @CrossOrigin
    public ResponseEntity<InputStreamResource> downloadTest(@PathVariable("name") String name) throws FileNotFoundException {
        return testService.download(name);
    }
 
    /**
     * 獲取文件的base64編碼
     * @param name
     * @return
     * @throws IOException
     */
    @GetMapping("/getBase64/{name}")
    public ActionResult getBase64(@PathVariable("name") String name) throws IOException {
        return testService.getBase64(name);
    }
 
}

Service接口就不貼了哈 

ServiceImpl 

package com.wft.service.impl;
 
import com.wft.model.ActionResult;
import com.wft.service.TestService;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.ResourceUtils;
import org.springframework.web.multipart.MultipartFile;
 
import java.io.*;
import java.nio.file.Files;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
 
@Service
public class TestServiceImpl implements TestService {
 
    /**
     * 文件上傳邏輯
     * @param file
     * @return
     * @throws IOException
     */
    @Override
    public ActionResult upload(MultipartFile file) throws IOException {
        if(file.isEmpty()) {
            return ActionResult.fail("文件不能為空");
        }
        // 上傳的文件名稱
        String originalFilename = file.getOriginalFilename();
        // 文件后綴
        String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
        // 使用uuid當(dāng)前文件名存儲(chǔ),防止名稱相同覆蓋
        String uuid = UUID.randomUUID().toString();
        String fileName = uuid + suffix;
        // 文件保存的路徑(我這里存在當(dāng)前項(xiàng)目下,所以獲取當(dāng)前項(xiàng)目的絕對(duì)路徑,然后拼接上圖片存放的文件夾的名稱)
        String savePath = ResourceUtils.getURL("resource").getPath();
        // 判斷是否存在resource目錄, 沒有則創(chuàng)建
        File dir = new File(savePath);
        if(dir != null && !dir.exists()) {
            dir.mkdir();
        }
        savePath = savePath + File.separator + fileName;
        // 文件上傳
        file.transferTo(new File(savePath));
        // 將文件存儲(chǔ)的名稱uuid和原文件名稱返回給前端
        Map<String, Object> map = new HashMap<>();
        map.put("id", uuid);
        map.put("name", originalFilename);
        // 將下載圖片的接口(返回文件流)路徑返回給前端,前端直接將服務(wù)器地址拼上該鏈接即可回顯圖片
        map.put("url", "/file/download/" + fileName);
        return ActionResult.success("上傳成功", map);
    }
 
    /**
     * 文件下載邏輯(文件流)
     * @param name
     * @return
     * @throws FileNotFoundException
     */
    @Override
    public ResponseEntity<InputStreamResource> download(String name) throws FileNotFoundException {
        String path = ResourceUtils.getURL("resource").getPath() + File.separator + name;
        File file = new File(path);
        if(!file.exists()) {
            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
        }
        // 創(chuàng)建輸入流
        InputStream inputStream = new FileInputStream(file);
        // 設(shè)置HTTP頭部信息
        HttpHeaders headers = new HttpHeaders();
        System.out.println(file.getName() + "---->>>文件名");
        headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + file.getName());
        // 返回文件流
        ResponseEntity<InputStreamResource> body = ResponseEntity.ok()
                .headers(headers)
                .contentType(MediaType.APPLICATION_OCTET_STREAM)
                .body(new InputStreamResource(inputStream));
        return body;
    }
 
    /**
     * 獲取文件的base64編碼
     * @param name
     * @return
     * @throws IOException
     */
    @Override
    public ActionResult getBase64(String name) throws IOException {
        String path = ResourceUtils.getURL("resource").getPath() + File.separator + name;
        File file = new File(path);
        if(!file.exists()) {
            return ActionResult.fail("文件不存在");
        }
        byte[] fileContent = Files.readAllBytes(file.toPath());
        String base64 = Base64.getEncoder().encodeToString(fileContent);
        base64 = "data:image/png;base64," + base64;
        return ActionResult.success((Object) base64);
    }
 
    /**
     * 將文件流轉(zhuǎn)為base64編碼(工具方法, service中接口沒有該方法)
     * @param response
     * @return
     * @throws IOException
     */
    public String streamToBase64(ResponseEntity<InputStreamResource> response) throws IOException {
        // 獲取InputStreamResource對(duì)象
        InputStreamResource resource = response.getBody();
        if (resource == null) {
            throw new IllegalArgumentException("Response body is null");
        }
        try (InputStream inputStream = resource.getInputStream();
             ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
 
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                byteArrayOutputStream.write(buffer, 0, bytesRead);
            }
            // 將InputStream轉(zhuǎn)換為字節(jié)數(shù)組
            byte[] fileBytes = byteArrayOutputStream.toByteArray();
            // 使用Base64編碼器進(jìn)行編碼
            String base64Encoded = Base64.getEncoder().encodeToString(fileBytes);
            base64Encoded = "data:image/png;base64," + base64Encoded;
            return base64Encoded;
        }
    }
}

代碼里面也都寫注釋了,大家一看應(yīng)該就明白了。

簡(jiǎn)單說一下思路把,存圖片的時(shí)候,我是以u(píng)uid當(dāng)作圖片的名稱存儲(chǔ)的,這樣即便是前端是兩個(gè)文件,但是名稱一樣,上傳之后也不會(huì)覆蓋掉原來的圖片。

然后圖片上傳完之后,我把回顯圖片的路徑返回給前端了,前端可以使用服務(wù)器地址(當(dāng)然開發(fā)環(huán)境下會(huì)有跨域問題,一般會(huì)直接用前綴)拼上返回的這個(gè)路徑即可回顯圖片。

返回的這個(gè)url其實(shí)就是后端編寫好的一個(gè)接口,返回的是個(gè)文件流,前端直接將完整的請(qǐng)求的后端的路徑放在img標(biāo)簽的src上,其實(shí)就相當(dāng)于發(fā)送了請(qǐng)求,所以這里注意這種方式回顯要求后端將改接口放在白名單中(即該接口不需要token校驗(yàn)),否則前端就不能像正常路徑一樣直接放在img的src上回顯,就要像普通的接口一樣調(diào)用接口,然后通過URL.createObjectURL(new Blob(res))的方式轉(zhuǎn)為路徑再復(fù)制給src。

然后我上面封裝了了個(gè)ActionResult的返回給前端的包裝類,也在這貼一下吧:

ActionResult 

package com.wft.model;
 
import lombok.Data;
 
@Data
public class ActionResult<T> {
 
    private Integer code;
 
    private String msg;
 
    private T data;
 
 
    public static ActionResult success() {
        ActionResult jsonData = new ActionResult();
        jsonData.setCode(200);
        jsonData.setMsg("success");
        return jsonData;
    }
 
    public static ActionResult success(String msg) {
        ActionResult jsonData = new ActionResult();
        jsonData.setCode(200);
        jsonData.setMsg(msg);
        return jsonData;
    }
 
    public static ActionResult success(Object object) {
        ActionResult jsonData = new ActionResult();
        jsonData.setData(object);
        jsonData.setCode(200);
        jsonData.setMsg("success");
        return jsonData;
    }
 
    public static ActionResult success(String msg, Object object) {
        ActionResult jsonData = new ActionResult();
        jsonData.setData(object);
        jsonData.setCode(200);
        jsonData.setMsg(msg);
        return jsonData;
    }
 
    public static ActionResult fail(Integer code, String message) {
        ActionResult jsonData = new ActionResult();
        jsonData.setCode(code);
        jsonData.setMsg(message);
        return jsonData;
    }
 
    public static ActionResult fail(String msg, String data) {
        ActionResult jsonData = new ActionResult();
        jsonData.setMsg(msg);
        jsonData.setData(data);
        return jsonData;
    }
 
    public static ActionResult fail(String msg) {
        ActionResult jsonData = new ActionResult();
        jsonData.setMsg(msg);
        jsonData.setCode(400);
        return jsonData;
    }
}

接下來再貼一下前端代碼:

<template>
  <div class="wft-test">
    <el-upload
      class="avatar-uploader"
      :action="baseURL + '/file/upload'"
      :show-file-list="false"
      :on-success="handleAvatarSuccess"
    >
      <img v-if="imageUrl" :src="baseURL + imageUrl" class="avatar" />
      <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
    </el-upload>
 
    <!-- 測(cè)試下載圖片 獲取文件流 -->
    <el-button @click="testDownload('12b83c8d-3d54-420d-a191-bd750fa571c4.png')">測(cè)試下載圖片流</el-button>
 
    <!-- 測(cè)試下載圖片 獲取base64 -->
    <el-button @click="testDownloadBase64('12b83c8d-3d54-420d-a191-bd750fa571c4.png')">測(cè)試下載圖片base64</el-button>
    <img style="width: 200px;height: 200px;" v-if="imgBase64" :src="imgBase64" alt="">
 
  </div>
</template>
<script setup lang='ts'>
import { ref } from 'vue';
import request from '@/utils/request';
 
const imageUrl = ref("");
const imgBase64 = ref("");
 
// 上傳成功回調(diào)
function handleAvatarSuccess(res: any) {
  if(res.code == 200) {
    imageUrl.value = res.data.url  // 正常成功回顯
  }
}
 
/**
 * 測(cè)試下載圖片(獲取文件流)
 * @param fileName 文件名
 */
function testDownload(fileName: string) {
  request({
    url: `/file/download/${fileName}`,
    method: 'get',
    responseType: 'blob'
  }).then((res: any) => {
    const link = document.createElement('a')
    link.href = URL.createObjectURL(new Blob([res]))
    link.download = 'test.png'
    document.body.appendChild(link)
    link.click()
    document.body.removeChild(link)
  })
}
 
/**
 * 測(cè)試下載圖片(獲取文件base64編碼)
 * @param fileName 
 */
function testDownloadBase64(fileName: string) {
  request({
    url: `/file/getBase64/${fileName}`,
    method: 'get'
  }).then((res: any) => {
    if(res.code == 200) {
      imgBase64.value = res.data
    }
  })
}
 
</script>
<style scoped>
.wft-test {
  width: 100%;
  height: 100%;
}
 
.avatar-uploader .avatar {
  width: 178px;
  height: 178px;
  display: block;
}
</style>
 
<style>
.avatar-uploader .el-upload {
  border: 1px dashed var(--el-border-color);
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  transition: var(--el-transition-duration-fast);
}
 
.avatar-uploader .el-upload:hover {
  border-color: var(--el-color-primary);
}
 
.el-icon.avatar-uploader-icon {
  font-size: 28px;
  color: #8c939d;
  width: 178px;
  height: 178px;
  text-align: center;
}
</style>

以上就是springboot實(shí)現(xiàn)圖片上傳與下載功能的詳細(xì)內(nèi)容,更多關(guān)于springboot圖片上傳下載的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 并行Stream與Spring事務(wù)相遇會(huì)發(fā)生什么?

    并行Stream與Spring事務(wù)相遇會(huì)發(fā)生什么?

    這篇文章主要介紹了并行Stream與Spring事務(wù)相遇會(huì)發(fā)生什么?文章主要解決實(shí)戰(zhàn)中的Bug及解決方案和技術(shù)延伸,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-05-05
  • springboot實(shí)現(xiàn)對(duì)注解的切面案例

    springboot實(shí)現(xiàn)對(duì)注解的切面案例

    這篇文章主要介紹了springboot實(shí)現(xiàn)對(duì)注解的切面過程,首先定義一個(gè)注解、再編寫對(duì)注解的切面只是記錄的執(zhí)行時(shí)間和打印方法,可以實(shí)現(xiàn)其他邏輯,需要的朋友可以參考一下
    2022-01-01
  • java實(shí)現(xiàn)大文件導(dǎo)出的實(shí)現(xiàn)與優(yōu)化

    java實(shí)現(xiàn)大文件導(dǎo)出的實(shí)現(xiàn)與優(yōu)化

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)大文件導(dǎo)出的實(shí)現(xiàn)與優(yōu)化的相關(guān)資料,文中的示例代碼講解詳細(xì),對(duì)我們深入了解java有一定的幫助,感興趣的小伙伴可以了解下
    2023-11-11
  • Spring接口ApplicationRunner用法詳解

    Spring接口ApplicationRunner用法詳解

    這篇文章主要介紹了Spring接口ApplicationRunner的作用和使用介紹,本文通過示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-08-08
  • Java計(jì)算兩個(gè)漢字相似度的實(shí)現(xiàn)方法

    Java計(jì)算兩個(gè)漢字相似度的實(shí)現(xiàn)方法

    有時(shí)候我們希望計(jì)算兩個(gè)漢字的相似度,比如文本的 OCR 等場(chǎng)景,用于識(shí)別糾正,本文給大家詳細(xì)介紹了Java計(jì)算兩個(gè)漢字相似度的實(shí)現(xiàn)方法,文中有詳細(xì)的實(shí)現(xiàn)代碼,需要的朋友可以參考下
    2023-11-11
  • java  設(shè)計(jì)模式之單例模式

    java 設(shè)計(jì)模式之單例模式

    這篇文章主要介紹了java 設(shè)計(jì)模式之單例模式的相關(guān)資料,需要的朋友可以參考下
    2017-02-02
  • Spring Core動(dòng)態(tài)代理的實(shí)現(xiàn)代碼

    Spring Core動(dòng)態(tài)代理的實(shí)現(xiàn)代碼

    通過JDK的Proxy方式或者CGLIB方式生成代理對(duì)象的時(shí)候,相關(guān)的攔截器已經(jīng)配置到代理對(duì)象中去了,接下來通過本文給大家介紹Spring Core動(dòng)態(tài)代理的相關(guān)知識(shí),需要的朋友可以參考下
    2021-10-10
  • Java中JDom解析XML_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    Java中JDom解析XML_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    JDOM是一種解析XML的Java工具包。DOM適合于當(dāng)今流行的各種語言,包括Java,JavaScripte,VB,VBScript,Perl,C,C++等。下面通過本文給大家介紹Java中JDom解析XML的方法,感興趣的朋友一起學(xué)習(xí)吧
    2017-07-07
  • Java中內(nèi)部類的概念與分類詳解

    Java中內(nèi)部類的概念與分類詳解

    一個(gè)類的定義放在另一個(gè)類的內(nèi)部,這個(gè)類就叫做內(nèi)部類,下面這篇文章主要給大家介紹了關(guān)于Java中內(nèi)部類的概念與分類的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2021-09-09
  • SpringBoot前后端交互、全局異常處理之后端異常信息拋到前端顯示彈窗

    SpringBoot前后端交互、全局異常處理之后端異常信息拋到前端顯示彈窗

    Spring Boot是一個(gè)用于構(gòu)建獨(dú)立的、基于生產(chǎn)級(jí)別的Spring應(yīng)用程序的框架,下面這篇文章主要給大家介紹了關(guān)于SpringBoot前后端交互、全局異常處理之后端異常信息拋到前端顯示彈窗的相關(guān)資料,需要的朋友可以參考下
    2024-08-08

最新評(píng)論