国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|JavaScript|易語言|

服務器之家 - 編程語言 - JAVA教程 - Spring Boot 與 Kotlin 上傳文件的示例代碼

Spring Boot 與 Kotlin 上傳文件的示例代碼

2021-03-25 10:17quanke JAVA教程

這篇文章主要介紹了Spring Boot 與 Kotlin 上傳文件的示例代碼,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

如果我們做一個小型的web站,而且剛好選擇的kotlin 和Spring Boot技術棧,那么上傳文件的必不可少了,當然,如果你做一個中大型的web站,那建議你使用云存儲,能省不少事情。

這篇文章就介紹怎么使用kotlin 和Spring Boot上傳文件

構建工程

如果對于構建工程還不是很熟悉的可以參考《我的第一個Kotlin應用》

完整 build.gradle 文件

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
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-plugin
apply 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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import name.quanke.kotlin.chaper11_5_6.storage.StorageFileNotFoundException
import name.quanke.kotlin.chaper11_5_6.storage.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.stream.Collectors
 
 
/**
 * 文件上傳控制器
 * Created by http://quanke.name on 2018/1/12.
 */
 
@Controller
class FileUploadController @Autowired
constructor(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>()
  }
 
}

上傳文件服務的接口

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import org.springframework.core.io.Resource
import org.springframework.web.multipart.MultipartFile
 
import java.nio.file.Path
import java.util.stream.Stream
 
interface StorageService {
 
  fun init()
 
  fun store(file: MultipartFile)
 
  fun loadAll(): Stream<Path>
 
  fun load(filename: String): Path
 
  fun loadAsResource(filename: String): Resource
 
  fun deleteAll()
 
}

上傳文件服務

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
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
class FileSystemStorageService @Autowired
constructor(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)
    }
 
  }
}

自定義異常

?
1
2
3
4
5
6
7
8
9
10
11
12
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)
}

配置文件上傳目錄

?
1
2
3
4
5
6
7
8
9
10
11
import org.springframework.boot.context.properties.ConfigurationProperties
 
@ConfigurationProperties("storage")
class StorageProperties {
 
  /**
   * Folder location for storing files
   */
  var location = "upload-dir"
 
}

啟動Spring Boot

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
 * 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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<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

?
1
2
3
4
5
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/

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:https://www.jianshu.com/p/d4952e71360b

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 福利一区二区 | 成人在线观看网站 | 久久久91精品国产一区二区三区 | 国产丝袜在线 | 免费成人福利视频 | 久久亚洲国产精品日日av夜夜 | 国产成人精品一区二区三区网站观看 | 天天爱天天草 | 中文字幕观看 | 久久亚洲欧美日韩精品专区 | 一区二区三区欧美 | 国产做a爰片久久毛片a我的朋友 | 欧美日韩一区二区电影 | 中文字幕专区 | 午夜视频免费在线观看 | 久久精品无码一区二区三区 | av网站在线看 | 国产精品国产三级国产aⅴ 亚洲精品免费在线观看 | 欧美日韩国产精品 | 日本日韩中文字幕 | 久久综合亚洲精品 | 国产精品久久九九 | 国产精品手机在线 | 日韩精品视频免费在线观看 | 狠狠干狠狠干 | 久久在线视频 | 精品久久久av | 精品少妇一区二区三区日产乱码 | 中文字幕亚洲一区二区va在线 | 在线观看一区二区三区四区 | 免费在线a | 欧美男人的天堂 | 国产在线综合网 | 精品欧美一区二区三区久久久 | 日本三级中文在线电影 | 中国黄色一级视频 | 中文字幕一区二区三区日韩精品 | a级三四级黄大片 | 女人性做爰免费网站 | 色偷偷噜噜噜亚洲男人的天堂 | 色屁屁影院 |