亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > 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教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
韩国三级电影久久久久久| 操人视频在线观看欧美| 日韩小视频在线观看| 亚洲免费视频网站| 久久精品国亚洲| 久久亚洲影音av资源网| 欧美日韩成人黄色| 日韩av在线直播| 久久久女女女女999久久| 91免费在线视频| 精品香蕉在线观看视频一| 国产激情999| 亚洲精品中文字幕有码专区| 亚洲欧美精品suv| 国产日韩在线观看av| 亚洲国产欧美自拍| 一个人看的www欧美| 亚洲国产精品成人精品| 97精品一区二区视频在线观看| 九九热这里只有在线精品视| 大伊人狠狠躁夜夜躁av一区| 不卡av电影院| 少妇激情综合网| 日韩在线免费视频观看| 国产精品久久av| 欧美电影免费观看电视剧大全| 青草热久免费精品视频| 国产精品入口夜色视频大尺度| 欧美性xxxx极品hd欧美风情| 午夜精品久久久久久久99热浪潮| 中文字幕亚洲欧美日韩2019| 最新国产成人av网站网址麻豆| 青青草国产精品一区二区| 一区二区福利视频| 992tv成人免费影院| 亚洲激情小视频| 国产精品美女久久久久av超清| 国产一区二区三区丝袜| 欧美一级视频免费在线观看| 午夜精品久久久久久久男人的天堂| 亚洲色图偷窥自拍| 欧美日韩国产123| www日韩中文字幕在线看| 色哟哟入口国产精品| 欧美野外wwwxxx| 在线成人免费网站| 久久久久久久久久久免费精品| 久久久精品在线观看| www日韩中文字幕在线看| 91国产精品视频在线| 日韩视频免费在线| 欧美华人在线视频| 亚洲美女在线看| 久久久久久久91| 欧美电影在线观看高清| 一区二区三区久久精品| 亚洲一区二区福利| 日本精品久久久久久久| 亚洲人高潮女人毛茸茸| 九九热这里只有精品免费看| 精品久久久香蕉免费精品视频| 性欧美xxxx视频在线观看| 日韩理论片久久| 57pao成人国产永久免费| 97免费视频在线播放| 乱亲女秽乱长久久久| 国产精品成人av性教育| 4p变态网欧美系列| 日av在线播放中文不卡| 成人羞羞国产免费| 精品日韩美女的视频高清| 日韩高清av在线| 欧美激情精品久久久久久变态| 茄子视频成人在线| 久久精品久久久久久| 亚洲区一区二区| 国产亚洲欧洲高清一区| 国产精品av网站| 中文字幕日韩av| 亚洲精品日韩av| 国产精品a久久久久久| 丁香五六月婷婷久久激情| 亚洲欧洲在线观看| 亚洲精品美女在线观看| 国产精品自拍偷拍| 国产美女精品免费电影| 亚洲美女av网站| 国模私拍视频一区| 国产视频综合在线| 成人国内精品久久久久一区| 日本精品免费一区二区三区| 日韩精品在线第一页| 在线观看国产精品淫| 欧美激情精品久久久久久大尺度| 亚洲欧美日韩国产成人| 欧美国产乱视频| 国产一区二区成人| 国外视频精品毛片| 国产精品自拍偷拍视频| 色偷偷综合社区| 欧美久久久精品| 美日韩精品视频免费看| 日本欧美中文字幕| 青青久久av北条麻妃黑人| 亚洲国产一区二区三区四区| 亚洲国产精品专区久久| 亚洲国产成人精品女人久久久| 一区二区成人av| 视频在线观看99| 精品久久久久久久久中文字幕| xxxx欧美18另类的高清| 精品久久久久久久久久久久久久| 国产精品海角社区在线观看| 欧美成人黄色小视频| 欧美一区深夜视频| 粗暴蹂躏中文一区二区三区| 亚洲视频在线免费观看| 日韩欧美成人免费视频| 国产乱肥老妇国产一区二| 久久久久久国产| 国产精品成人免费电影| 国内精品免费午夜毛片| 亚洲美女动态图120秒| 国产激情视频一区| 91精品免费久久久久久久久| 91国语精品自产拍在线观看性色| 国产成人综合亚洲| 欧美综合在线观看| 精品国产一区二区三区久久狼5月| 92看片淫黄大片看国产片| 成人在线免费观看视视频| 欧美日韩另类字幕中文| 日韩国产在线看| 97精品欧美一区二区三区| 国产亚洲成av人片在线观看桃| 97av在线影院| 热久久视久久精品18亚洲精品| 亚洲精品福利视频| 亚洲天堂久久av| 国产精品高潮呻吟久久av黑人| 国产精品高潮呻吟久久av野狼| 亚洲午夜精品久久久久久性色| 深夜福利亚洲导航| 26uuu国产精品视频| 久久91超碰青草是什么| 综合国产在线观看| 中文字幕日本欧美| 亚洲理论在线a中文字幕| 日韩欧美有码在线| 午夜精品一区二区三区在线视频| 狠狠躁天天躁日日躁欧美| 97婷婷涩涩精品一区| 久久久精品一区二区三区| 色噜噜国产精品视频一区二区| 国产精品激情自拍| 欧美专区日韩视频| 一区二区成人av| 亚洲第一福利网| 精品国产区一区二区三区在线观看| 国产精品美女久久久久av超清| 欧美肥臀大乳一区二区免费视频| 2020国产精品视频| 在线观看国产欧美| 国产精品免费久久久久影院|