当前位置: 首页 > 知识库问答 >
问题:

spring webflux FilePart如何验证mime类型?

程墨竹
2023-03-14
@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和文件大小?

共有1个答案

张俊茂
2023-03-14

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-上下文:- 依赖关系:- 验证类:- 我错过了什么?