java通过url获取 jpg、png、pdf 文件格式

目录

前言

如果一个 url

例如 : https://i-blog.csdnimg.cn/direct/4b54f5f678bb404f8f92007792e46592.png

上面的链接我们可以轻松的通过 后缀 .png 判断它的文件类型,但是很多时候有的 url 链接是不带这种后缀的,并且有时候即使 url 带了.png 后缀,它下载下来也不一定是 png 文件 ,所以需要下载文件后根据文件字节码去判断。

本文通过文件url 获取到文件字节数组,通过文件魔数(Magic Number)识别文件类型,比只靠文件后缀识别更可靠。

依赖

xml 复制代码
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>5.3.29</version>
        </dependency>

枚举类和工具类

java 复制代码
import lombok.AllArgsConstructor;
import lombok.Getter;

/**
 * 文件类型枚举
 *
 */
@Getter
@AllArgsConstructor
public enum FileTypeEnum {

    /**
     * JEPG.
     */
    JPEG("FFD8FF", "image/jpg"),


    /**
     * PNG.
     */
    PNG("89504E47", "image/png"),

    /**
     * Adobe Acrobat.
     */
    PDF("255044462D312E", "application/pdf"),

    OTHER("OTHER", "OTHER");

    private String value;

    private String contentType;
}
java 复制代码
import com.hai.tang.model.FileTypeEnum;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Base64;

public class FileTypeUtils {

    /**
     * 从文件 url 下载获取文件字节数组
     * @param url 文件url
     * @turn FileTypeEnum 文件类型枚举
     */
    public static ResponseEntity<byte[]> downloadFile(final String url) {
        SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
        // 设置超时时间为5秒
        requestFactory.setReadTimeout(5000);
        requestFactory.setConnectTimeout(60000);

        RestTemplate restTemplate = new RestTemplate(requestFactory);
        HttpHeaders headers = new HttpHeaders();
        ResponseEntity<byte[]> entity = restTemplate.exchange(url, HttpMethod.GET, new HttpEntity<>(headers), byte[].class);
        return entity;
    }

    /**
     * 从文件字节数组中前16比特获取文件类型
	 * @param bytes 文件字节数组
	 * @turn FileTypeEnum 文件类型枚举
     */
    public static FileTypeEnum getFileType(byte[] bytes) {
        int length = Math.min(bytes.length, 16);
        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < length; i++) {
            sb.append(String.format("%02X", bytes[i]));
        }
        String fileHead = sb.toString();
        for (FileTypeEnum type : FileTypeEnum.values()) {
            if (fileHead.startsWith(type.getValue())) {
                return type;
            }
        }
        return FileTypeEnum.OTHER;
    }
    
     /**
     * 将 base64 文件保存到本地
     *
     * @param fileBase64 文件base64
     * @param fileType 文件类型 FileTypeEnum 里的 contentType
     * @param outPath 文件要保存到的本地路径,如: C:\Users\haitang\Desktop
     *
     */
    public static void save(String fileBase64, String fileType, String outPath) throws IOException {
        //将 base64 文件 转为 字节数组
        byte[] bytes = Base64.getDecoder().decode(fileBase64);
        String suffix = fileType.split("/")[1];
        DateTimeFormatter f = DateTimeFormatter.ofPattern("yyyy-MM-dd HH-mm-ss");
        String time = LocalDateTime.now().format(f);
        String fileName = time + "." + suffix;
        //文件保存到本地
        Files.write(Paths.get(outPath + File.separator + fileName), bytes);
    }

}

测试:

用于测试的三个 png、jpg、pdf 文件链接

java 复制代码
https://i-blog.csdnimg.cn/direct/4b54f5f678bb404f8f92007792e46592.png
https://pic3.zhimg.com/v2-e88c84efc46685275936b278784c0d16_1440w.jpg
https://www.kkoworld.com/kitablar/Nikolas_Sparks_Sevimli_Con_eng.pdf

测试代码如下,通过工具类下载 url 链接为字节数组然后打印文件类型

java 复制代码
import com.hai.tang.util.FileTypeUtils;
import org.springframework.http.ResponseEntity;  

public class MainServer {
	public static void main(String[] args) throws Exception {
        String fileUrl = "https://i-blog.csdnimg.cn/direct/4b54f5f678bb404f8f92007792e46592.png";
        ResponseEntity<byte[]> entity = FileTypeUtils.downloadFile(fileUrl);
        if (entity.hasBody() && null != entity.getBody()) {
            //获取文件类型 image/jpg 或 image/png 或 application/pdf
            String attachmentType = FileTypeUtils.getFileType(entity.getBody()).getContentType();
            System.out.println(attachmentType);

            //将 entity.getBody() 即文件字节数组 转化为 base64 编码的字符串(可用于存储到数据库)
            String attachmentBase64Stream = DatatypeConverter.printBase64Binary(entity.getBody());
            // base64 编码的文件字符串 输出到 C:\Users\haitang\Desktop 保存
            FileTypeUtils.save(attachmentBase64Stream,attachmentType,"C:\\Users\\haitang\\Desktop");
        }
    }
}
相关推荐
API快乐传递者32 分钟前
1688 跨境电商 API 接口实战指南:从寻源到代采的全链路技术方案
java·前端·数据库
孔明click3333 分钟前
不想写代码,但想要集成一个登录页面?Sa-Token-Quick-Login 帮你实现!
java·sa-token·开源·springboot·登录·权限·权限认证
曹牧1 小时前
C#与Java后台交互
java·windows·microsoft·c#
张晓祥-长草颜团子1 小时前
【重庆两江新区歌词】
java
东小西1 小时前
【SAA实战】第 2 篇:模型与消息——ReactAgent 怎么挑模型、怎么传消息
java·后端·spring
码匠许师傅1 小时前
【C++ 面试真题】35. 聊聊 C++ 的万能引用(T&&)和完美转发(std::forward)
java·c++·面试
十年Java程序媛1 小时前
注解已经加上,但是事务没有回滚?拆解 AOP 代理底层原因 + 代码示例
java
μθημα1 小时前
K8s Pod 管理实战:虚拟机环境下的具体命令与步骤
java·docker·kubernetes
数据狐(Datafox)1 小时前
1688.item_search工程实战:1688商品列表API分页采集与B2B货源数据分析落地
java·前端·数据分析
省长1 小时前
不想写代码,但想要集成一个登录页面?Sa-Token-Quick-Login 帮你实现!
java·后端·开源