@PostMapping("/users/avatar")
suspend fun uploadAvatar(@RequestPart("file") filePartMono: Mono<FilePart>) {
filePartMono.map{ part -> part.content().map{ it.asInputStream().readAllBytes() }
.map { it /* ??? */ }
}
// ...
}
在无Reactor栈上,我是这样做的:
uploadAvatar(@RequestParam("file") MultipartFile file) {
String contentType = file.getContentType().toLowerCase();
List<String> valid = Arrays.asList("image/jpg", "image/jpeg", "image/png");
if (file.isEmpty() || !valid.contains(contentType)) {
throw new UploadException("Invalid image format or empty file", HttpStatus.UNPROCESSABLE_ENTITY);
}
if (file.getSize() > IMAGE_MAX_FILE_SIZE) {
throw new UploadException("Image too big (max " + (IMAGE_MAX_FILE_SIZE / 1000) + " kB )", HttpStatus.UNPROCESSABLE_ENTITY);
}
try {
// try to read file as image to ensure it is an image
ImageIO.read(file.getInputStream());
} catch (IOException e) {
throw new UploadException("Invalid image", HttpStatus.UNPROCESSABLE_ENTITY);
}
try {
byte[] bytes = file.getBytes();
userService.storeAvatar(bytes);
} catch (IOException e) {
throw new UploadException("Could not store image", HttpStatus.INTERNAL_SERVER_ERROR);
}
}
但是FilePart不提供相同的API(例如contentType)。
如何从filepart
获取contentType和文件大小?
FilePart
有可以像这样访问的头。
@PostMapping(value = ["/upload"], consumes = [MediaType.MULTIPART_FORM_DATA_VALUE])
suspend fun upload(@RequestPart(name = "file") file: Mono<FilePart>) {
val filePart = file.awaitFirstOrNull() ?: throw Exception()
println(filePart.headers().contentType)
println(filePart.headers().contentLength)
}
但是,我认为仅仅依靠header
来获取内容类型
并不是一个好主意。因此,可以使用Tika
库进行类型检测。考虑到您使用的是gradle
,您可以这样做。
在build.gradle.kts
中
implementation("org.apache.tika:tika-core:1.26")
@PostMapping(value = ["/upload"], consumes = [MediaType.MULTIPART_FORM_DATA_VALUE])
suspend fun upload(@RequestPart(name = "file") file: Mono<FilePart>) : Response {
val filePart = file.awaitFirstOrNull() ?: throw Exception()
val inputStream = filePart.content().awaitFirst().asInputStream()
val detectedFileTye = getFilePartFileType(filePart.filename(), inputStream)
...
}
private suspend fun getFilePartFileType(fileName: String, inputStream: InputStream): String? = coroutineScope {
val mimeTypeDeferred = async(Dispatchers.IO) {
Tika().detect(inputStream, fileName)
}
mimeTypeDeferred.await()
}
MIME(多用途Internet邮件扩展)类型告诉浏览器如何处理某些类型的文件。 当文件发送到您网站访问者的浏览器时,它也会发送该文件的MIME类型。 MIME类型告诉浏览器文件类型以及如何将文件提供给用户。 例如,如果将.js文件发送到浏览器,则还会发送application/JavaScript MIME类型以告知浏览器.js文件是JavaScript文件,浏览器会相应地处理该文件。 大多数M
问题内容: 在我正在使用的Web应用程序中,用户可以单击指向CSV文件的链接。没有为mime- type设置标题,因此浏览器仅将其呈现为文本。我希望此文件以.csv文件的形式发送,因此用户可以直接使用calc,excel,gnumeric等打开它。 该代码可以在我的计算机上正常工作(不是一直如此吗?),但在另一台计算机上不起作用。 我的浏览器是FF 3.0.1(在Linux上)的每晚构建。它无法使
我正在使用XPages FileUpload控件将一些附件(.xml文件)保存到文档中。默认情况下,Domino正在保存。具有“text/xml”MIME类型的xml。但是我需要它是“application/xml”。设置FileUpload控件的“MIME类型”选项没有帮助,因为Domino可以识别文件类型并对其进行更改。 有没有办法完成这项任务并手动将附件MIME类型切换到自定义类型?
最初设计MIME(多用途Internet邮件扩展)媒体类型,以便电子邮件可以包括除纯文本之外的信息。 MIME媒体类型表示以下内容 - 消息的不同部分(如文本和附件)如何组合到消息中。 指定消息的每个部分的方式。 编码不同项目以进行传输的方式,以便即使设计为仅使用ASCII文本的软件也可以处理该消息。 现在MIME类型不只是用于电子邮件; 它们已经被Web服务器采用,作为告诉Web浏览器向他们发送
我有一个布尔字段,我想验证它只有“true”或“false”作为值(没有引号)。但是这个字段也允许“true”或“false”作为值(带引号),我想对其进行限制。 我尝试使用@Pattern注释来匹配这些值。但我有以下错误: javax.validation.expectiontedTypeException:HV000030:找不到约束“javax.validation.Constraints.
这个问题已经被问了很多次了,即使是在经历了所有的解决方案之后,我也无法让hibernate validator工作。 控制器类:- servlet-上下文:- 依赖关系:- 验证类:- 我错过了什么?