真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

SpringBoot+thymeleaf如何實現(xiàn)文件上傳下載功能

小編給大家分享一下Spring Boot + thymeleaf如何實現(xiàn)文件上傳下載功能,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

成都創(chuàng)新互聯(lián)公司專注為客戶提供全方位的互聯(lián)網(wǎng)綜合服務(wù),包含不限于成都網(wǎng)站設(shè)計、網(wǎng)站制作、臨淄網(wǎng)絡(luò)推廣、微信小程序定制開發(fā)、臨淄網(wǎng)絡(luò)營銷、臨淄企業(yè)策劃、臨淄品牌公關(guān)、搜索引擎seo、人物專訪、企業(yè)宣傳片、企業(yè)代運營等,從售前售中售后,我們都將竭誠為您服務(wù),您的肯定,是我們最大的嘉獎;成都創(chuàng)新互聯(lián)公司為所有大學(xué)生創(chuàng)業(yè)者提供臨淄建站搭建服務(wù),24小時服務(wù)熱線:18980820575,官方網(wǎng)址:www.cdcxhl.com

最近同事問我有沒有有關(guān)于技術(shù)的電子書,我打開電腦上的小書庫,但是郵件發(fā)給他太大了,公司又禁止用文件夾共享,于是花半天時間寫了個小的文件上傳程序,部署在自己的Linux機(jī)器上。

提供功能: 1 .文件上傳 2.文件列表展示以及下載

原有的上傳那塊很丑,寫了點js代碼優(yōu)化了下,最后界面顯示如下圖:

Spring Boot + thymeleaf如何實現(xiàn)文件上傳下載功能 

先給出成果,下面就一步步演示怎么實現(xiàn)。

1.新建項目

首先當(dāng)然是新建一個spring-boot工程,你可以選擇在網(wǎng)站初始化一個項目或者使用IDE的Spring Initialier功能,都可以新建一個項目。這里我從IDEA新建項目:

Spring Boot + thymeleaf如何實現(xiàn)文件上傳下載功能 

下一步,然后輸入group和artifact,繼續(xù)點擊next:

Spring Boot + thymeleaf如何實現(xiàn)文件上傳下載功能 

這時候出現(xiàn)這個模塊選擇界面,點擊web選項,勾上Web,證明這是一個webapp,再點擊Template Engines選擇前端的模板引擎,我們選擇Thymleaf,spring-boot官方也推薦使用這個模板來替代jsp。

Spring Boot + thymeleaf如何實現(xiàn)文件上傳下載功能

Spring Boot + thymeleaf如何實現(xiàn)文件上傳下載功能

最后一步,然后等待項目初始化成功。

Spring Boot + thymeleaf如何實現(xiàn)文件上傳下載功能 

2.pom設(shè)置

首先檢查項目需要添加哪些依賴,直接貼出我的pom文件:



 4.0.0
 com.shuqing28
 upload
 0.0.1-SNAPSHOT
 jar
 upload
 Demo project for Spring Boot
 
 org.springframework.boot
 spring-boot-starter-parent
 1.5.9.RELEASE
  
 
 
 UTF-8
 UTF-8
 1.8
 
 
 
  org.springframework.boot
  spring-boot-starter
 
 
  org.springframework.boot
  spring-boot-starter-thymeleaf
 
 
  org.springframework.boot
  spring-boot-configuration-processor
  true
 
 
  org.springframework.boot
  spring-boot-starter-test
  test
 
 
 
  org.webjars
  bootstrap
  3.3.5
 
 
 
  org.webjars.bower
  jquery
  2.2.4
 
 
 
 
  
  org.springframework.boot
  spring-boot-maven-plugin
  
 
 

可以查看到 spring-boot-starter-thymeleaf 包含了webapp,最后兩個webjars整合了bootstrap和jquery,其它的等代碼里用到再說。

最后一個Spring boot maven plugin是系統(tǒng)創(chuàng)建時就添加的,它有以下好處:

1 . 它能夠打包classpath下的所有jar,構(gòu)建成一個可執(zhí)行的“über-jar”,方便用戶轉(zhuǎn)移服務(wù)

2 . 自動搜索 public static void main() 方法并且標(biāo)記為可執(zhí)行類

3 . 根據(jù)spring-boot版本,提供內(nèi)建的依賴解釋。

3. 上傳文件控制器

如果你只是使用SpringMVC上傳文件,是需要配置一個 MultipartResolver 的bean的,或者在 web.xml 里配置一個 ,不過借助于spring-boot的自動配置,你什么都不必做。直接寫控制器類,我們在 src/main/java 下新建controller的package,并且新建FileUploadController:

package com.shuqing28.upload.controller;
import com.shuqing28.uploadfiles.pojo.Linker;
import com.shuqing28.uploadfiles.exceptions.StorageFileNotFoundException;
import com.shuqing28.uploadfiles.service.StorageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;
@Controller
public class FileUploadController {
  private final StorageService storageService;
  @Autowired
  public FileUploadController(StorageService storageService) {
    this.storageService = storageService;
  }
  @GetMapping("/")
  public String listUploadedFiles(Model model)throws IOException {
    List linkers = storageService.loadAll().map(
        path -> new Linker(MvcUriComponentsBuilder.fromMethodName(FileUploadController.class,
            "serveFile", path.getFileName().toString()).build().toString(),
            path.getFileName().toString())
    ).collect(Collectors.toList());
    model.addAttribute("linkers", linkers);
    return "uploadForm";
  }
  @GetMapping("/files/{filename:.+}")
  @ResponseBody
  public ResponseEntity serveFile(@PathVariable String filename) {
    Resource file = storageService.loadAsResource(filename);
    return ResponseEntity.ok().header(HttpHeaders.CONTENT_DISPOSITION,
        "attachment; filename=\"" + file.getFilename() + "\"").body(file);
  }
  @PostMapping("/")
  public String handleFileUpload(@RequestParam("file") MultipartFile file,
                  RedirectAttributes redirectAttributes) {
    storageService.store(file);
    redirectAttributes.addFlashAttribute("message",
        "You successfully uploaded " + file.getOriginalFilename() + "!");
    return "redirect:/";
  }
  @ExceptionHandler(StorageFileNotFoundException.class)
  public ResponseEntity handleStorageFileNotFound(StorageFileNotFoundException exc) {
    return ResponseEntity.notFound().build();
  }
}

類定義處添加了 @Controller 注解,證明這是一個Controller,每個方法前添加了 @GetMapping 和 @PostMapping 分別相應(yīng)Get和Post請求。

首先是 @GetMapping("/") ,方法 listUploadedFiles ,顧名思義,顯示文件列表,這里我們借助于storageService遍歷文件夾下的所有文件,并且用map方法提合成了鏈接和文件名列表,返回了一個Linker對象的數(shù)組,Linker對象是一個簡單pojo,只包含下面兩部分:

private String fileUrl;
private String fileName;

這個方法包含了對Java8中Stream的使用,如果有不理解的可以看看這篇文章 Java8 特性詳解(二) Stream API .

接下來是 @GetMapping("/files/{filename:.+}") ,方法是 serveFile ,該方法提供文件下載功能,還是借助于storageservice,后面會貼出storageservice的代碼。最后使用ResponseEntity,把文件作為body返回給請求方。

@PostMapping("/") 的 handleFileUpload 使用Post請求來上傳文件,參數(shù) @RequestParam("file") 提取網(wǎng)頁請求里的文件對象,還是使用storageService來保存對象,最后使用重定向來刷新網(wǎng)頁,并且給出成功上傳的message。

4. 文件處理

上面Controller調(diào)用的很多方法由StorageService提供,我們定義一個接口,包含以下方法:

package com.shuqing28.uploadfiles.service;
import org.springframework.core.io.Resource;
import org.springframework.web.multipart.MultipartFile;
import java.nio.file.Path;
import java.util.stream.Stream;
public interface StorageService {
  void init();
  void store(MultipartFile file);
  Stream loadAll();
  Path load(String filename);
  Resource loadAsResource(String filename);
  void deleteAll();
}

因為我這里只是借助于本地文件系統(tǒng)處理文件的長傳下載,所以有了以下實現(xiàn)類:

package com.shuqing28.uploadfiles.service;
import com.shuqing28.uploadfiles.exceptions.StorageException;
import com.shuqing28.uploadfiles.exceptions.StorageFileNotFoundException;
import com.shuqing28.uploadfiles.config.StorageProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.stereotype.Service;
import org.springframework.util.FileSystemUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.stream.Stream;
@Service
public class FileSystemStorageService implements StorageService {
  private final Path rootLocation;
  @Autowired
  public FileSystemStorageService(StorageProperties properties) {
    this.rootLocation = Paths.get(properties.getLocation());
  }
  @Override
  public void init() {
    try {
      Files.createDirectories(rootLocation);
    }
    catch (IOException e) {
      throw new StorageException("Could not initialize storage", e);
    }
  }
  @Override
  public void store(MultipartFile file) {
    String filename = StringUtils.cleanPath(file.getOriginalFilename());
    try {
      if (file.isEmpty()) {
        throw new StorageException("Failed to store empty file" + filename);
      }
      if (filename.contains("..")) {
        // This is a security check
        throw new StorageException(
            "Cannot store file with relative path outside current directory "
                + filename);
      }
      Files.copy(file.getInputStream(), this.rootLocation.resolve(filename), StandardCopyOption.REPLACE_EXISTING);
    } catch (IOException e) {
      throw new StorageException("Failed to store file" + filename, e);
    }
  }
  @Override
  public Stream loadAll() {
    try {
      return Files.walk(this.rootLocation, 1)
          .filter(path -> !path.equals(this.rootLocation))
          .map(path->this.rootLocation.relativize(path));
    }
    catch (IOException e) {
      throw new StorageException("Failed to read stored files", e);
    }
  }
  @Override
  public Path load(String filename) {
    return rootLocation.resolve(filename);
  }
  @Override
  public Resource loadAsResource(String filename) {
    try {
      Path file = load(filename);
      Resource resource = new UrlResource(file.toUri());
      if (resource.exists() || resource.isReadable()) {
        return resource;
      }
      else {
        throw new StorageFileNotFoundException(
            "Could not read file: " + filename);
      }
    }
    catch (MalformedURLException e) {
      throw new StorageFileNotFoundException("Could not read file: " + filename, e);
    }
  }
  @Override
  public void deleteAll() {
    FileSystemUtils.deleteRecursively(rootLocation.toFile());
  }
}

這個類也基本運用了Java的NIO,使用Path對象定義了location用于文件的默認(rèn)保存路徑。

先看 store 方法,store接受一個MultipartFile對象作為參數(shù),想比于傳統(tǒng)JSP中只是傳二進(jìn)制字節(jié)數(shù)組,MultipartFile提供了很多方便調(diào)用的方法讓我們可以獲取到上傳文件的各項信息:

public interface MultipartFile extends InputStreamSource {
 String getName();
 String getOriginalFilename();
 String getContentType();
 boolean isEmpty();
 long getSize();
 byte[] getBytes() throws IOException;
 InputStream getInputStream() throws IOException;
 void transferTo(File dest) throws IOException, IllegalStateException;
}

代碼里使用了Files的copy方法把文件流拷到location對應(yīng)的Path里,當(dāng)然我們也可以使用transferTo方法保存文件, file.transferTo(this.rootLocation.resolve(filename).toFile());

loadAll方法加載該路徑下的所有文件Path信息, loadAsResource 則是加載文件為一個Resource對象,再看Controller的代碼,最后是接受一個Resource對象作為body返回給請求方。

5. 前端模板

最后定義了前端模板,這里依舊先看代碼:



  Share Files



  
                                                     Choose             
    
                Submit       Reset           
                       
  function bs_input_file() {     $(".input-file").before(       function() {         if ( ! $(this).prev().hasClass('input-ghost') ) {           var element = $(".input-ghost");           element.change(function(){             element.next(element).find('input').val((element.val()).split('\\').pop());           });           $(this).find("button.btn-choose").click(function(){             element.click();           });           $(this).find("button.btn-reset").click(function(){             element.val(null);             $(this).parents(".input-file").find('input').val('');           });           $(this).find('input').css("cursor","pointer");           $(this).find('input').mousedown(function() {             $(this).parents('.input-file').prev().click();             return false;           });           return element;         }       }     );   }   $(function() {     bs_input_file();   });

這里重要的地方還是

標(biāo)簽內(nèi)的內(nèi)容, enctype 一定要寫成 multipart/form-data ,使用POST上傳文件,原有的上傳控件很丑,所以做了一個text+input放在表面,在下面放了一個隱形的上傳文件的input,可以自己看看代碼,本文就不啰嗦了。

下面還放了一個list用于展示文件列表,這里我們獲取到服務(wù)端提供的linkers對象,不斷foreach就可以獲得里面的兩個元素fileUrl和fileName。

這里jquery換成了微軟的CDN,webjars的總是引入不進(jìn)來,不知道什么原因。

其它設(shè)置

在 src/main/resources/application.properties 里設(shè)置上傳文件大小限制

spring.http.multipart.max-file-size=128MB
spring.http.multipart.max-request-size=128MB

另外在``還設(shè)置了文件默認(rèn)保存路徑:

package com.shuqing28.uploadfiles.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("storage")
public class StorageProperties {
  private String location = "/home/jenkins/upload-files/";
  public String getLocation() {
    return location;
  }
  public void setLocation(String location) {
    this.location = location;
  }
}

這里注意,由于StorageProperties的設(shè)置,在Application的那個類中要添加上

@EnableConfigurationProperties注解
@SpringBootApplication
@EnableConfigurationProperties(StorageProperties.class)
public class UploadApplication {
 public static void main(String[] args) {
 SpringApplication.run(UploadApplication.class, args);
 }
}

以上是“Spring Boot + thymeleaf如何實現(xiàn)文件上傳下載功能”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!


當(dāng)前題目:SpringBoot+thymeleaf如何實現(xiàn)文件上傳下載功能
網(wǎng)頁網(wǎng)址:http://weahome.cn/article/ipiisj.html

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部