判断图片的像素, 视频的时长, 文件的类型, 文件的大小是否超过指定值

该文提供了一个名为FileUploadUtils的Java工具类,用于处理文件上传时的校验工作,包括图片像素、视频时长和文件大小的检查。此外,它还利用Tika库确定文件的真实类型,并通过OkHttp从HTTP/2获取网络资源。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

package com.topsports.decision.engine.common.core.util;

import com.topsports.decision.engine.common.core.exception.BizException;
import okhttp3.*;
import org.apache.tika.metadata.HttpHeaders;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.metadata.TikaMetadataKeys;
import org.apache.tika.parser.AutoDetectParser;
import org.apache.tika.parser.ParseContext;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;
import org.xml.sax.helpers.DefaultHandler;
import ws.schild.jave.MultimediaObject;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;

/**
 * @author yukun.yan
 * @description FileUploadUtils 目标文件根据自定义规则校验
 * @date 2023/5/17 14:48
 */
public class FileUploadUtils {

    private FileUploadUtils() {
        throw new UnsupportedOperationException();
    }

    /**
     * 初始化文件解析器
     */
    private static final AutoDetectParser parser = new AutoDetectParser();
    private static final ParseContext parseContext = new ParseContext();

    /**
     * 判断上传的图片文件像素是否超过指定值
     *
     * @param file      MultipartFile对象
     * @param maxPixels 最大像素值
     * @return true         表示图片像素没有超过指定值,false表示图片像素超过了指定值maxPixels
     */
    public static boolean isImagePixelExceeded(MultipartFile file, int maxPixels) {
        try (InputStream inputStream = file.getInputStream()) {
            BufferedImage image = ImageIO.read(inputStream);
            AssertUtils.notNull(image, BizException.biz("Invalid image file"));
            int width = image.getWidth();
            int height = image.getHeight();
            int pixels = width * height;
            return pixels < maxPixels;
        } catch (Exception e) {
            throw BizException.biz(e.getMessage());
        }
    }

    /**
     * 判断上传的视频文件时长是否超过指定值
     *
     * @param multipartFile     文件
     * @param maxDurationSecond 最大支持的视频时长(秒)
     * @return 不超过指定的秒数返回true
     */
    public static boolean isVideoDurationExceeded(MultipartFile multipartFile, int maxDurationSecond) {
        try {
            // 创建临时文件夹, 会自动删除
            File tempFile = File.createTempFile("temp", null);
            // 拷贝
            multipartFile.transferTo(tempFile);
            MultimediaObject multimediaObject = new MultimediaObject(tempFile);
            long durationMillisecond = multimediaObject.getInfo().getDuration();
            // 手动删除
            tempFile.delete();
            return durationMillisecond < maxDurationSecond * 1000L;
        } catch (Exception e) {
            throw BizException.biz(e.getMessage());
        }
    }

    /**
     * 判断上传的文件大小是否超过指定值
     *
     * @param file      文件
     * @param maxSizeMb 文件最大大小
     * @return 没有超过指定值maxSize, 返回true
     */
    public static boolean isSizeExceeded(MultipartFile file, long maxSizeMb) {
        if (!isFileExist(file)) {
            throw BizException.biz("File does not exist");
        }
        long size = file.getSize();
        // 没有超过指定值
        return size < (maxSizeMb * 1024 * 1024);
    }

    /**
     * 校验文件类型是不是我们预期的类型
     *
     * @param file              文件
     * @param expectedMimeTypes 预期的文件类型的Pattern, 可以自定义任意文件类型
     * @return 不匹配, 返回false
     */
    public static boolean isFileTypeMatch(MultipartFile file, List<Pattern> expectedMimeTypes) {
        // 获取文件类型
        String fileType = getFileRealType(file);
        for (Pattern expectedMimeType : expectedMimeTypes) {
            if (expectedMimeType.matcher(fileType).matches()) {
                return true;
            }
        }
        return false;
    }

    /**
     * 获取文件类型, 根据文件后缀名判断无法准确判断类型
     *
     * @param file
     * @return
     */
    public static String getFileRealType(MultipartFile file) {
        Metadata metadata = new Metadata();
        metadata.add(TikaMetadataKeys.RESOURCE_NAME_KEY, file.getName());
        try (InputStream stream = file.getInputStream()) {
            parser.parse(stream, new DefaultHandler(), metadata, parseContext);
        } catch (Exception e) {
            throw BizException.biz(e.getMessage());
        }
        return metadata.get(HttpHeaders.CONTENT_TYPE);
    }

    /**
     * 根据使用HTTP/2获取网络资源
     *
     * @param url
     * @return
     * @throws IOException
     */
    public static MultipartFile getMultipartFileByHttp2(String url) {
        OkHttpClient client = new OkHttpClient.Builder()
                .protocols(Arrays.asList(Protocol.HTTP_2, Protocol.HTTP_1_1))
                .build();
        Request request = new Request.Builder()
                .url(url)
                .build();
        Response response;
        try {
            response = client.newCall(request).execute();
        } catch (Exception e) {
            throw BizException.biz(e.getMessage());
        }
        AssertUtils.isTrue(response.isSuccessful(), BizException.biz("Unexpected response code:%s" + response.code()));
        ResponseBody body = response.body();
        AssertUtils.notNull(body, BizException.biz("response body is null"));

        try (InputStream inputStream = body.byteStream()) {
            String fileName = interceptFileNameByUrl(url);
            return new MockMultipartFile(fileName, fileName, MediaType.MULTIPART_FORM_DATA_VALUE, inputStream);
        } catch (Exception e) {
            throw BizException.biz(e.getMessage());
        }
    }

    /**
     * 根据url截取文件名
     *
     * @param url
     * @return
     */
    public static String interceptFileNameByUrl(String url) {
        if (StringUtils.isBlank(url)) {
            throw new IllegalArgumentException("url is null");
        }
        return url.substring(url.lastIndexOf("/") + 1);
    }

    /**
     * 指定文件是否存在
     *
     * @param file
     * @return
     */
    public static boolean isFileExist(MultipartFile file) {
        return file != null && !file.isEmpty();
    }

}

用到maven依赖

<dependency>
                <groupId>commons-fileupload</groupId>
                <artifactId>commons-fileupload</artifactId>
                <version>1.4</version>
                <scope>compile</scope>
            </dependency>
            <dependency>
                <groupId>ws.schild</groupId>
                <artifactId>jave-all-deps</artifactId>
                <version>3.3.1</version>
            </dependency>
            <dependency>
                <groupId>org.apache.tika</groupId>
                <artifactId>tika-core</artifactId>
                <version>1.24.1</version>
            </dependency>

### 处理 `MultipartFile` 类型文件 为了使 `MultimediaObject` 类能够处理或接收来自前端上传的 `MultipartFile` 类型文件,在Spring Boot应用程序中通常需要遵循特定的设计模式。具体来说,可以通过创建服务层来处理业务逻辑,并通过控制器层暴露API端点。 #### 创建 MultimediaObject 实体类 首先定义实体类用于表示多媒体对象: ```java public class MultimediaObject { private Long id; private String name; private byte[] content; // Getters and Setters omitted for brevity } ``` #### 修改 Service 层以支持 MultipartFile 接收 接着修改现有的 `MediaService` 或者新建一个专门的服务接口用来保存接收到的数据流到数据库或者其他存储介质中: ```java @Service public class MediaServiceImpl implements MediaService { @Override public void saveMedia(String fileName, InputStream inputStream) throws IOException { // 将输入流转存为字节数组或其他持久化操作 ByteArrayOutputStream buffer = new ByteArrayOutputStream(); int nRead; byte[] data = new byte[1024]; while ((nRead = inputStream.read(data, 0, data.length)) != -1) { buffer.write(data, 0, nRead); } buffer.flush(); // 假设这里有一个方法可以将byte数组转换成MultimediaObject并保存它 MultimediaObject multimediaObject = new MultimediaObject(); multimediaObject.setName(fileName); multimediaObject.setContent(buffer.toByteArray()); // Save to database or other storage mechanism... } } ``` #### 更新 Controller 来调用新的 Service 方法 最后调整原有的控制台代码以便于当接收到文件时能正确地传递给服务层进行进一步的操作: ```java @RestController @RequestMapping("media") public class MediaController { @Autowired private MediaService mediaService; @PostMapping("/upload") public ResponseEntity<String> uploadMedia(@RequestParam("file") MultipartFile file, @RequestParam("userId") Long userId) throws IOException { if (file.isEmpty()) { return ResponseEntity.badRequest().body("Please select a valid file"); } try { String fileName = file.getOriginalFilename(); InputStream in = file.getInputStream(); mediaService.saveMedia(fileName, in); return ResponseEntity.ok("用户 " + userId + " 正在对 " + fileName + " 文件进行在线解析"); } catch (Exception e) { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage()); } } } ``` 上述实现展示了如何构建一个简单的流程,其中包含了从客户端接受多部分表单数据(`MultipartFile`)并通过自定义的服务层将其转化为适合内部使用的格式(如本例中的 `MultimediaObject`)。此过程还涉及到了异常处理机制以确保即使出现问题也能向用户提供有意义的信息反馈[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值