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

网友投稿 469 2023-02-25


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

如果我们做一个小型的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-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

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 {

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()

}

}

上传文件服务的接口

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

fun load(filename: String): Path

fun loadAsResource(filename: String): Resource

fun deleteAll()

}

上传文件服务

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 {

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) {

SpringApplication.run(Application::class.java, *args)

}

}

}

创建一个简单的 html模板 src/main/resources/templates/uploadForm.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/


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:angular写一个列表的选择全选交互组件的示例
下一篇:区块链java代码实现
相关文章

 发表评论

暂时没有评论,来抢沙发吧~