首页 > 开发 > Java > 正文

Spring Boot 与 Kotlin 上传文件的示例代码

2024-07-13 10:17:03
字体:
来源:转载
供稿:网友

如果我们做一个小型的web站,而且刚好选择的kotlin 和Spring Boot技术栈,那么上传文件的必不可少了,当然,如果你做一个中大型的web站,那建议你使用云存储,能省不少事情。

这篇文章就介绍怎么使用kotlin 和Spring Boot上传文件

构建工程

如果对于构建工程还不是很熟悉的可以参考《我的第一个Kotlin应用》

完整 build.gradle 文件

group 'name.quanke.kotlin'version '1.0-SNAPSHOT'buildscript {  ext.kotlin_version = '1.2.10'  ext.spring_boot_version = '1.5.4.RELEASE'  repositories {    mavenCentral()  }  dependencies {    classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"    classpath("org.springframework.boot:spring-boot-gradle-plugin:$spring_boot_version")//    Kotlin整合SpringBoot的默认无参构造函数,默认把所有的类设置open类插件    classpath("org.jetbrains.kotlin:kotlin-noarg:$kotlin_version")    classpath("org.jetbrains.kotlin:kotlin-allopen:$kotlin_version")      }}apply plugin: 'kotlin'apply plugin: "kotlin-spring" // See https://kotlinlang.org/docs/reference/compiler-plugins.html#kotlin-spring-compiler-pluginapply plugin: 'org.springframework.boot'jar {  baseName = 'chapter11-5-6-service'  version = '0.1.0'}repositories {  mavenCentral()}dependencies {  compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"  compile "org.springframework.boot:spring-boot-starter-web:$spring_boot_version"  compile "org.springframework.boot:spring-boot-starter-thymeleaf:$spring_boot_version"  testCompile "org.springframework.boot:spring-boot-starter-test:$spring_boot_version"  testCompile "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version"}compileKotlin {  kotlinOptions.jvmTarget = "1.8"}compileTestKotlin {  kotlinOptions.jvmTarget = "1.8"}

创建文件上传controller

import name.quanke.kotlin.chaper11_5_6.storage.StorageFileNotFoundExceptionimport name.quanke.kotlin.chaper11_5_6.storage.StorageServiceimport org.springframework.beans.factory.annotation.Autowiredimport org.springframework.core.io.Resourceimport org.springframework.http.HttpHeadersimport org.springframework.http.ResponseEntityimport org.springframework.stereotype.Controllerimport org.springframework.ui.Modelimport org.springframework.web.bind.annotation.*import org.springframework.web.multipart.MultipartFileimport org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilderimport org.springframework.web.servlet.mvc.support.RedirectAttributesimport java.io.IOExceptionimport java.util.stream.Collectors/** * 文件上传控制器 * Created by http://quanke.name on 2018/1/12. */@Controllerclass FileUploadController @Autowiredconstructor(private val storageService: StorageService) {  @GetMapping("/")  @Throws(IOException::class)  fun listUploadedFiles(model: Model): String {    model.addAttribute("files", storageService        .loadAll()        .map { path ->          MvcUriComponentsBuilder              .fromMethodName(FileUploadController::class.java, "serveFile", path.fileName.toString())              .build().toString()        }        .collect(Collectors.toList()))    return "uploadForm"  }  @GetMapping("/files/{filename:.+}")  @ResponseBody  fun serveFile(@PathVariable filename: String): ResponseEntity<Resource> {    val file = storageService.loadAsResource(filename)    return ResponseEntity        .ok()        .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=/"" + file.filename + "/"")        .body(file)  }  @PostMapping("/")  fun handleFileUpload(@RequestParam("file") file: MultipartFile,             redirectAttributes: RedirectAttributes): String {    storageService.store(file)    redirectAttributes.addFlashAttribute("message",        "You successfully uploaded " + file.originalFilename + "!")    return "redirect:/"  }  @ExceptionHandler(StorageFileNotFoundException::class)  fun handleStorageFileNotFound(exc: StorageFileNotFoundException): ResponseEntity<*> {    return ResponseEntity.notFound().build<Any>()  }}

上传文件服务的接口

import org.springframework.core.io.Resourceimport org.springframework.web.multipart.MultipartFileimport java.nio.file.Pathimport java.util.stream.Streaminterface StorageService {  fun init()  fun store(file: MultipartFile)  fun loadAll(): Stream<Path>  fun load(filename: String): Path  fun loadAsResource(filename: String): Resource  fun deleteAll()}

上传文件服务

import org.springframework.beans.factory.annotation.Autowiredimport org.springframework.core.io.Resourceimport org.springframework.core.io.UrlResourceimport org.springframework.stereotype.Serviceimport org.springframework.util.FileSystemUtilsimport org.springframework.util.StringUtilsimport org.springframework.web.multipart.MultipartFileimport java.io.IOExceptionimport java.net.MalformedURLExceptionimport java.nio.file.Filesimport java.nio.file.Pathimport java.nio.file.Pathsimport java.nio.file.StandardCopyOptionimport java.util.stream.Stream@Serviceclass FileSystemStorageService @Autowiredconstructor(properties: StorageProperties) : StorageService {  private val rootLocation: Path  init {    this.rootLocation = Paths.get(properties.location)  }  override fun store(file: MultipartFile) {    val filename = StringUtils.cleanPath(file.originalFilename)    try {      if (file.isEmpty) {        throw StorageException("Failed to store empty file " + filename)      }      if (filename.contains("..")) {        // This is a security check        throw StorageException(            "Cannot store file with relative path outside current directory " + filename)      }      Files.copy(file.inputStream, this.rootLocation.resolve(filename),          StandardCopyOption.REPLACE_EXISTING)    } catch (e: IOException) {      throw StorageException("Failed to store file " + filename, e)    }  }  override fun loadAll(): Stream<Path> {    try {      return Files.walk(this.rootLocation, 1)          .filter { path -> path != this.rootLocation }          .map { path -> this.rootLocation.relativize(path) }    } catch (e: IOException) {      throw StorageException("Failed to read stored files", e)    }  }  override fun load(filename: String): Path {    return rootLocation.resolve(filename)  }  override fun loadAsResource(filename: String): Resource {    try {      val file = load(filename)      val resource = UrlResource(file.toUri())      return if (resource.exists() || resource.isReadable) {        resource      } else {        throw StorageFileNotFoundException(            "Could not read file: " + filename)      }    } catch (e: MalformedURLException) {      throw StorageFileNotFoundException("Could not read file: " + filename, e)    }  }  override fun deleteAll() {    FileSystemUtils.deleteRecursively(rootLocation.toFile())  }  override fun init() {    try {      Files.createDirectories(rootLocation)    } catch (e: IOException) {      throw StorageException("Could not initialize storage", e)    }  }}

自定义异常

open class StorageException : RuntimeException {  constructor(message: String) : super(message)  constructor(message: String, cause: Throwable) : super(message, cause)}class StorageFileNotFoundException : StorageException {  constructor(message: String) : super(message)  constructor(message: String, cause: Throwable) : super(message, cause)}

配置文件上传目录

import org.springframework.boot.context.properties.ConfigurationProperties@ConfigurationProperties("storage")class StorageProperties {  /**   * Folder location for storing files   */  var location = "upload-dir"}

启动Spring Boot

/** * Created by http://quanke.name on 2018/1/9. */@SpringBootApplication@EnableConfigurationProperties(StorageProperties::class)class Application {  @Bean  internal fun init(storageService: StorageService) = CommandLineRunner {    storageService.deleteAll()    storageService.init()  }  companion object {    @Throws(Exception::class)    @JvmStatic    fun main(args: Array<String>) {      SpringApplication.run(Application::class.java, *args)    }  }}

创建一个简单的 html模板 src/main/resources/templates/uploadForm.html

<html xmlns:th="http://www.thymeleaf.org"><body><div th:if="${message}">  <h2 th:text="${message}"/></div><div>  <form method="POST" enctype="multipart/form-data" action="/">    <table>      <tr>        <td>File to upload:</td>        <td><input type="file" name="file"/></td>      </tr>      <tr>        <td></td>        <td><input type="submit" value="Upload"/></td>      </tr>    </table>  </form></div><div>  <ul>    <li th:each="file : ${files}">      <a th:href="${file}" rel="external nofollow" th:text="${file}"/>    </li>  </ul></div></body></html>

配置文件 application.yml

spring: http:  multipart:   max-file-size: 128KB   max-request-size: 128KB

更多Spring Boot 和 kotlin相关内容,欢迎关注 《Spring Boot 与 kotlin 实战》

源码:

https://github.com/quanke/spring-boot-with-kotlin-in-action/

参考:

https://spring.io/guides/gs/uploading-files/

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持VeVb武林网。


注:相关教程知识阅读请移步到JAVA教程频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表