java代码实现百度网盘文件上传返回下载链接-已封装工具类!可用于maven,spring-boot,spring-boot-cloud等项目,以及思路全解!

阿丹:

        查找晚上很多案例都出现各种问题所以专门出一篇文章。因为业务涉及到需要较大的内存空间。使用oss以及fastdfs来说一个对金钱需求太大。fastdfs对服务器的损耗太大。于是寻找第三方。百度网盘相对来说就不错。本文章集合百度官方文档。以及网上案例。进行优化以及业务逻辑描述分析。来相对完美的完成和实现。

官方文档:

官方文档上有错误码等等信息。在使用本文章的时候如果出现文章没有涉及到的内容需要去官方文档查看。

百度网盘开放平台帮助与支持

百度网盘开放平台帮助与支持-官方文档

逻辑图示

 本文章使用的模式为:授权码模式

文件上传:

获取相应token:

 准备工作:

查看本专栏之前的文章

百度开放平台申请认证获取用户授权code值,获取access_token以及refresh等

上代码:

代码结构:

其中:

                constant为连接常量

                constantData是理解变量

                tokenUtils为刷新以及判断token是否过期工具类 

                file为主题

连接百度网盘固定常量

连接百度网盘的常量

package com.shp.dev.service.baidu;

/**
 * @Description: TODO 百度网盘基本常量信息
 */

public interface Constant {
    //单位mb
    // 普通用户单个分片大小固定为4MB(文件大小如果小于4MB,无需切片,直接上传即可),单文件总大小上限为4G。
    //普通会员用户单个分片大小上限为16MB,单文件总大小上限为10G。
    //超级会员用户单个分片大小上限为32MB,单文件总大小上限为20G。
    Integer UNIT=32;
    String APP_ID="";
    String APP_NAME="";
    String APP_KEY="";
    String SECRET_KEY="";
    String SING_key="";
    //使用登录来创建连接//可以实现上传不同文件夹可使用测试目录来拼接
    
    String APP_PATH="/apps/"+APP_NAME+"/测试目录/";

    //操作文件 copy, mover, rename, delete
    String FILE_MANAGER_URL=" https://pan.baidu.com/rest/2.0/xpan/file";

    //预上传
    String GET_READY_FILE_URL="https://pan.baidu.com/rest/2.0/xpan/file";

    //分片上传
    String SLICING_UPLOAD_FILE_URL="https://d.pcs.baidu.com/rest/2.0/pcs/superfile2";

    //下载文件
    String DOWN_LOUE_URL="https://pan.baidu.com/rest/2.0/xpan/multimedia";

    //文件搜索
    String FILE_SEARCH="https://pan.baidu.com/rest/2.0/xpan/file?method=search";


}


动态连接数据:

说明:

        使用了设计模式的单例模式,使用懒汉式来保证每次使用的动态改变的连接数据为正确。

文件中的中文需要根据上一篇文章的步骤来获取。

package com.shp.dev.service.baidu;

import lombok.Data;
import org.springframework.stereotype.Component;

import java.util.Date;

import static com.shp.dev.service.baidu.Constant.APP_KEY;
import static com.shp.dev.service.baidu.Constant.SECRET_KEY;

/**
 * 因为如果遇到atoken过期需要根据rtoken来刷新数据
 * 所以这个类需要使用单例模式的懒汉式来完成
 * 1、保证后台工具类中的软件tokenUtils来更新的时候操作的都是同一个ConstantData类
 * 这样获取到第一个code就能完成,从此不需要手动获取code来换取快开始的token
 * */
@Data
@Component
public class ConstantData {
    /**后期上线使用整合spring-boog-cloud 使用nacos来读取配置文件中的这些基本信息就能完成
     * 就能实现修改配置文件即可
     * */
    private ConstantData(String GET_CODE_URL, String CODE, String GET_TOKEN_BY_CODE, String RTOKEN, String ATOKEN) {
        this.GET_CODE_URL = GET_CODE_URL;
        this.CODE = CODE;
        this.GET_TOKEN_BY_CODE = GET_TOKEN_BY_CODE;
        this.RTOKEN = RTOKEN;
        this.ATOKEN = ATOKEN;
    }

    /**
     * 使用懒汉式单例模式
     * */
    public  static  synchronized  ConstantData getInstance() {
        //判断如果没有这个单例模式就开始创建
        if( instance == null){
            instance = new ConstantData();
        }
        //开始校验
        instance.doSomething();
        //就算有了这个实例也是返回这个实例
        return instance;
    }
    private ConstantData(){

    }
    /**
     * 直接进行判断atoken是否过期
     * */
    public void doSomething() {
        // 这里是你单例类的逻辑代码
        //获取当前时间
        Date date = new Date();
        long time = date.getTime();
        //获取刷新token的时间
        if(instance.getGetAccessTokenTime()==null){
            Date date1 = new Date();
            date1.setTime(第一次获取atoken的时间毫秒数);
            this.GetAccessTokenTime = date1;
        }
        //使用时间校验如果当前时间减去获取token的时间大于过期时间那么就进行刷新校验
        if((time-instance.GetAccessTokenTime.getTime())>this.getExpiresIn()*1000){
            System.out.println("tokeny已经获取开始重新获取");
            //刷新atoken以及rtoken
            TokenUtils.getAtoken();
        }else{
            System.out.println("token没有过期可以继续使用");
        }
    }
    private static ConstantData instance;
    String GET_CODE_URL="https://openapi.baidu.com/oauth/2.0/authorize?response_type=code&client_id="+APP_KEY+"&redirect_uri=oob&scope=basic,netdisk&display=tv&qrcode=1&force_login=1";

    //获取到的授权码
    String CODE="";

    //根据授权码换取token
    String GET_TOKEN_BY_CODE="https://openapi.baidu.com/oauth/2.0/token?grant_type=authorization_code&code="+CODE+"&client_id="+APP_KEY+"&client_secret="+SECRET_KEY+"&redirect_uri=oob";

    //获取到的TOKEN
    String RTOKEN="第一次需要手动填写";
    String ATOKEN= "第一次需要手动填写";

    /**
     * 因为官网文档返回值中存在expiress_in值为acccess_token过期时间
     * 通过追加字段来完成
     * 1、追加字段刷新atoken日期
     * 2、追加字段获取过期秒数
     * 追加字段
     * atoken过期时间
     * */
    Long ExpiresIn = 2592000L;
    Date GetAccessTokenTime;
}

获取刷新atoken工具类 

注意:

        需要注意错误码,如果使用了错误的rtoken或者错误的atoken,会触发安全协议。注意判断。

package com.shp.dev.service.baidu;

import com.alibaba.fastjson.JSON;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;

@Component
public class TokenUtils {

    public static void main(String[] args) {
        String atoken = getAtoken();
        System.out.println(atoken);
    }
    public static String getAtoken() {
        ConstantData constantData = ConstantData.getInstance();
        String url1 = "https://openapi.baidu.com/oauth/2.0/token?" +
                "grant_type=refresh_token&" +
                "refresh_token=" + constantData.getRTOKEN() +
                "&client_id=" + Constant.APP_KEY +
                "&client_secret=" + Constant.SECRET_KEY;
        //原因是因为:每次刷新token的时候返回了不仅是新的atoken以及新的rtoken
        System.out.println(url1);

        try {
            URL url = new URL(url1);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String inputLine;
            StringBuffer response = new StringBuffer();
            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine);
            }
            in.close();
            //  System.out.println(response.toString());
            Map map = JSON.parseObject(response.toString(), Map.class);
            System.out.println("Respons"+map);
            //获取用户校验token
            String atoken = (String) map.get("access_token");
            //获取用来刷新的refreash
            String rtoken = (String) map.get("refresh_token");
            String expiresIn = (String) map.get("expires_in");
            System.out.println("atoken"+atoken);
            System.out.println("rtoken"+rtoken);
            System.out.println("expiresIn"+expiresIn);
            //进行重新赋值
            constantData.setATOKEN(atoken);
            constantData.setRTOKEN(rtoken);
            constantData.setExpiresIn(Long.valueOf(expiresIn));

            // Return the atoken
            return atoken;
        } catch (Exception e) {
            System.out.println(e);
        }
        return "触发安全协议";
    }
}

主体工具类(百度网盘预上传、分片、上传、回显下载链接)

使用本地文件地址,以及本地文件名字来进行保存
  @SneakyThrows
    public static void main(String[] args) {
        //不能有空格
        String filePath = "D:\\个人文件\\";
        String fileName = "222.jpg";
        System.out.println(save(filePath, fileName));
    }
保存文件
/**
     * 阿丹 保存文件
     * @param: filePath 文件路径
     * @param: fileName 文件名称
     * return 文件下载地址
     */
    private static String save(String filePath, String fileName) {
        //本地文件地址
        String absoluteFilePath = filePath + fileName;
        //云端文件地址
        String cloudPath = APP_PATH + fileName;

        //文件分片并获取md5值
        File file = new File(absoluteFilePath);
        File[] separate = separate(absoluteFilePath, UNIT);
        StringBuffer md5s = new StringBuffer();
        if (separate.length == 1) {
            md5s.append(getMD5(separate[0]));
        }
        if (separate.length > 1) {
            for (int i = 0; i < separate.length; i++) {
                md5s.append(getMD5(separate[i]) + "\",\"");
                log.info("正在分片,{}{}", separate[i].toString(), i);
            }
            String s = md5s.toString();
            md5s = new StringBuffer(s.substring(0, md5s.length() - 3));
        }

        //预上传
        String precreate = precreate(cloudPath, file.length(), 0, md5s.toString());
        log.info("预上传{}", precreate);

        //分片上传
        String upload = upload(cloudPath, (String) new JSONObject(precreate).get("uploadid"), separate);
        log.info("分片上传{}", upload);

        //创建文件
        String create = create(fileName, file.length(), 0, md5s.toString());
        log.info("创建文件{}", create);

        //获取下载地址
        String downUrl = getDownUrl(fileName);
        log.info("获取下载地址{}", downUrl);

        return downUrl;
    }
获取下载地址
 /**
     * 阿丹 获取下载地址
     * @param: fileName 文件名
     */
    /**
     * 对于返回这个文件的问题
     * */
    private static String getDownUrl(String fileName) {
        //获取单例模式下面的连接数据
        ConstantData constantData = ConstantData.getInstance();
        //添加参数recursion=1使用递归来进行查询
        //之前报错分析为:前面的查询没有指定目录,现在查询使用递归来查找文件中所有的值
        //现在可以正常使用并返回了
        String fileSearch = HttpUtil.get(FILE_SEARCH + "&recursion=1&access_token=" + constantData.getATOKEN() + "&key=" + fileName);
        JSONObject jsonObject = new JSONObject(fileSearch);
        System.out.println("jsonObject"+jsonObject);
        JSONArray list = jsonObject.getJSONArray("list");
        JSONObject listJSONObject = list.getJSONObject(0);
        Long fs_id = listJSONObject.getLong("fs_id");
        String url = DOWN_LOUE_URL + "?method=filemetas&access_token=" + constantData.getATOKEN() + "&fsids=[" + fs_id + "]&dlink=1";
        String s = HttpUtil.get(url);
        JSONObject sJsonObject = new JSONObject(s);
        JSONArray jsonArray = sJsonObject.getJSONArray("list");
        JSONObject jsonObjectClient = jsonArray.getJSONObject(0);
        String dlink = jsonObjectClient.getStr("dlink");
        return dlink;
    }
创建文件
/**
     * 阿丹 创建文件
     * @param: fileName 文件名称
     * @param: size 文件大小 字节
     * @param: isDir 0文件 1目录(设置为目录是 size要设置为0)
     * @param: blockList (文件的md5值) 可以把文件分为多个,然后分批上传
     * @return: java.lang.String
     */
    private static String create(String fileName, Long size, Integer isDir, String blockList) {
        //获取数据对象
        ConstantData instance = ConstantData.getInstance();
        String strURL = FILE_MANAGER_URL + "?method=create&access_token=" + instance.getATOKEN();
        String params = "path=" + APP_PATH + fileName + "&size=" + size + "&autoinit=1&block_list=[\"" + blockList + "\"]&isdir=" + isDir;
        return open(strURL, params, "GET");
    }
分片文件
 /**
     * 阿丹 分片上传
     * @param: path 上传到百度网盘的地址
     * @param: uploadid 上传的id
     * @param: filePath 本地文件的地址
     * @return: java.lang.String
     */
    private static String upload(String path, String uploadid, File[] files) {
        //获取数据对象
        ConstantData instance = ConstantData.getInstance();
        try {

            for (int i = 0; i < files.length; i++) {
                String url = SLICING_UPLOAD_FILE_URL + "?method=upload" +
                        "&access_token=" + instance.getATOKEN() +
                        "&type=tmpfile&partseq=" + i +
                        "&path=" + path +
                        "&uploadid=" + uploadid;
                String s = sendFile(url, files[i]);
                log.info("正在上传分片文件{}{}", s, i);
            }

            return path;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
预上传
   /**
     * 阿丹 预上传
     * @param: cloudPath 云端路径
     * @param: size 文件大小 字节
     * @param: isDir 0文件 1目录(设置为目录是 size要设置为0)
     * @param: blockList (文件的md5值) 可以把文件分为多个,然后分批上传
     * @return: java.lang.String
     */
    private static String precreate(String cloudPath, Long size, Integer isDir, String blockList) {
        //获取数据对象
        ConstantData instance = ConstantData.getInstance();
        String strURL = GET_READY_FILE_URL + "?method=precreate&access_token=" + instance.getATOKEN();
        String params = "path=" + cloudPath + "&size=" + size + "&autoinit=1&block_list=[\"" + blockList + "\"]&isdir=" + isDir;
        return open(strURL, params, "POST");
    }
获取md5值
 /**
     * 阿丹 获取md5值
     * String path 文件地址
     */
    private final static String[] strHex = {"0", "1", "2", "3", "4", "5",
            "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};

    private static String getMD5(File path) {
        StringBuilder buffer = new StringBuilder();
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] b = md.digest(org.apache.commons.io.FileUtils.readFileToByteArray(path));
            for (int value : b) {
                int d = value;
                if (d < 0) {
                    d += 256;
                }
                int d1 = d / 16;
                int d2 = d % 16;
                buffer.append(strHex[d1]).append(strHex[d2]);
            }
            return buffer.toString();
        } catch (Exception e) {
            return null;
        }
    }
拼接请求连接
/**
     * 阿丹
     * @param: strURL 网址,可以是 http://aaa?bbb=1&ccc=2 拼接的
     * @param: params 拼接的body参数也就是form表单的参数  ddd=1&eee=2
     * @param: method 请求方式 get/post/put/delte等
     * @return: java.lang.String
     */
    private static String open(String strURL, String params, String method) {
        try {
            URL url = new URL(strURL);// 创建连接
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setDoOutput(true);
            connection.setDoInput(true);
            connection.setUseCaches(false);
            connection.setInstanceFollowRedirects(true);
            connection.setRequestMethod(method);
            connection.setRequestProperty("Accept", "application/json");// 设置接收数据的格式
            connection.setRequestProperty("Content-Type", "application/json");// 设置发送数据的格式
            connection.connect();
            OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream(), StandardCharsets.UTF_8);// utf-8编码
            out.append(params);
            out.flush();
            out.close(); // 读取响应
            int length = connection.getContentLength();// 获取长度
            InputStream is = connection.getInputStream();
            if (length != -1) {
                byte[] data = new byte[length];
                byte[] temp = new byte[512];
                int readLen = 0;
                int destPos = 0;
                while ((readLen = is.read(temp)) > 0) {
                    System.arraycopy(temp, 0, data, destPos, readLen);
                    destPos += readLen;
                }
                return new String(data, StandardCharsets.UTF_8);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
发送Post请求
 /**
     * 向指定 URL 发送POST方法的请求
     *
     * @param url   发送请求的 URL
     * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
     * @return 所代表远程资源的响应结果
     */
    public static String sendFile(String url, String param, String file) {
        if (url == null || param == null) {
            return url;
        }

        PrintWriter out = null;
        BufferedReader in = null;
        String result = "";
        try {
            URL realUrl = new URL(url);
            // 打开和URL之间的连接
            URLConnection conn = realUrl.openConnection();
            // 设置通用的请求属性
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent",
                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            //设置链接超时时间为2秒
            conn.setConnectTimeout(1000);
            //设置读取超时为2秒
            conn.setReadTimeout(1000);
            // 获取URLConnection对象对应的输出流
            out = new PrintWriter(conn.getOutputStream());
            out.write(file);
            // 发送请求参数
            out.print(param);
            // flush输出流的缓冲
            out.flush();
            // 定义BufferedReader输入流来读取URL的响应
            in = new BufferedReader(
                    new InputStreamReader(conn.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            System.out.println(e.getMessage() + "地址:" + url);
            return null;
        }
        //使用finally块来关闭输出流、输入流
        finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                System.out.println(ex.getMessage());
                return null;
            }
        }
        return result;
    }
filePath对文件进行分片
  /**
     * @param: filePath
     * @param: unit 单个文件大小
     * @return: 返回文件的目录
     */
    private static File[] separate(Object obj, Integer unit) {

        try {

            InputStream bis = null;//输入流用于读取文件数据
            OutputStream bos = null;//输出流用于输出分片文件至磁盘
            File file = null;
            if (obj instanceof String) {
                file = new File((String) obj);
            }
            if (obj instanceof File) {
                file = (File) obj;
            }

            String filePath = file.getAbsolutePath();
            File newFile = new File(filePath.substring(0, filePath.lastIndexOf("\\") + 1));
            String directoryPath = newFile.getAbsolutePath();
            long splitSize = unit * 1024 * 1024;//单片文件大小,MB
            if (file.length() < splitSize) {
                log.info("文件小于单个分片大小,无需分片{}", file.length());
                return new File[]{file};
            }


            //分片一
            bis = new BufferedInputStream(new FileInputStream(file));
            long writeByte = 0;//已读取的字节数
            int len = 0;
            byte[] bt = new byte[1024];
            while (-1 != (len = bis.read(bt))) {
                if (writeByte % splitSize == 0) {
                    if (bos != null) {
                        bos.flush();
                        bos.close();
                    }
                    bos = new BufferedOutputStream(new FileOutputStream(filePath + "." + (writeByte / splitSize + 1) + ".part"));
                }
                writeByte += len;
                bos.write(bt, 0, len);
            }
            
            log.info("文件分片成功!");

            //排除被分片的文件
            if (newFile.isDirectory()) {
                File[] files = newFile.listFiles();
                File[] resultFiles = new File[files.length - 1];
                int j = 0;
                for (int i = 0; i < files.length; i++) {
                    if (!files[i].equals(file)) {
                        resultFiles[j] = files[i];
                        j++;
                    }
                }
                return resultFiles;
            }

            bos.flush();
            bos.close();
            bis.close();
            return new File[0];
        } catch (Exception e) {
            log.info("文件分片失败!");
            e.printStackTrace();
        }
        return null;
    }
发送文件
 /**
     * 阿丹 发送文件
     * @param: url 发送地址
     * @param: file 发送文件
     * @return: java.lang.String
     */
    private static String sendFile(String url, File file) {
        try {
            MultipartEntityBuilder builder = MultipartEntityBuilder.create();
            builder.setContentType(ContentType.MULTIPART_FORM_DATA);
            builder.addBinaryBody("file", file);
            String body = "";
            //创建httpclient对象
            CloseableHttpClient client = HttpClients.createDefault();
            //创建post方式请求对象
            HttpPost httpPost = new HttpPost(url);
            //设置请求参数
            HttpEntity httpEntity = builder.build();
            httpPost.setEntity(httpEntity);
            //执行请求操作,并拿到结果(同步阻塞)
            CloseableHttpResponse response = client.execute(httpPost);
            //获取结果实体
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                //按指定编码转换结果实体为String类型
                body = EntityUtils.toString(entity, "utf-8");
            }
            EntityUtils.consume(entity);
            //释放链接
            response.close();
            return body;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

完全代码

主体代码!!!

import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.shp.dev.service.baidu.ConstantData;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;

import static com.shp.dev.service.baidu.Constant.*;

/**
 * 阿丹 上传文件到百度网盘
 */

@Slf4j
public class FileUtils {

    @SneakyThrows
    public static void main(String[] args) {
        //不能有空格
        String filePath = "D:\\个人文件\\";
        String fileName = "222.jpg";
        System.out.println(save(filePath, fileName));
    }

    /**
     * 阿丹 保存文件
     * @param: filePath 文件路径
     * @param: fileName 文件名称
     * return 文件下载地址
     */
    private static String save(String filePath, String fileName) {
        //本地文件地址
        String absoluteFilePath = filePath + fileName;
        //云端文件地址
        String cloudPath = APP_PATH + fileName;

        //文件分片并获取md5值
        File file = new File(absoluteFilePath);
        File[] separate = separate(absoluteFilePath, UNIT);
        StringBuffer md5s = new StringBuffer();
        if (separate.length == 1) {
            md5s.append(getMD5(separate[0]));
        }
        if (separate.length > 1) {
            for (int i = 0; i < separate.length; i++) {
                md5s.append(getMD5(separate[i]) + "\",\"");
                log.info("正在分片,{}{}", separate[i].toString(), i);
            }
            String s = md5s.toString();
            md5s = new StringBuffer(s.substring(0, md5s.length() - 3));
        }

        //预上传
        String precreate = precreate(cloudPath, file.length(), 0, md5s.toString());
        log.info("预上传{}", precreate);

        //分片上传
        String upload = upload(cloudPath, (String) new JSONObject(precreate).get("uploadid"), separate);
        log.info("分片上传{}", upload);

        //创建文件
        String create = create(fileName, file.length(), 0, md5s.toString());
        log.info("创建文件{}", create);

        //获取下载地址
        String downUrl = getDownUrl(fileName);
        log.info("获取下载地址{}", downUrl);

        return downUrl;
    }


    /**
     * 阿丹 获取下载地址
     * @param: fileName 文件名
     */
    /**
     * 对于返回这个文件的问题
     * */
    private static String getDownUrl(String fileName) {
        //获取单例模式下面的连接数据
        ConstantData constantData = ConstantData.getInstance();
        //添加参数recursion=1使用递归来进行查询
        //之前报错分析为:前面的查询没有指定目录,现在查询使用递归来查找文件中所有的值
        //现在可以正常使用并返回了
        String fileSearch = HttpUtil.get(FILE_SEARCH + "&recursion=1&access_token=" + constantData.getATOKEN() + "&key=" + fileName);
        JSONObject jsonObject = new JSONObject(fileSearch);
        System.out.println("jsonObject"+jsonObject);
        JSONArray list = jsonObject.getJSONArray("list");
        JSONObject listJSONObject = list.getJSONObject(0);
        Long fs_id = listJSONObject.getLong("fs_id");
        String url = DOWN_LOUE_URL + "?method=filemetas&access_token=" + constantData.getATOKEN() + "&fsids=[" + fs_id + "]&dlink=1";
        String s = HttpUtil.get(url);
        JSONObject sJsonObject = new JSONObject(s);
        JSONArray jsonArray = sJsonObject.getJSONArray("list");
        JSONObject jsonObjectClient = jsonArray.getJSONObject(0);
        String dlink = jsonObjectClient.getStr("dlink");
        return dlink;
    }

    /**
     * 阿丹 创建文件
     * @param: fileName 文件名称
     * @param: size 文件大小 字节
     * @param: isDir 0文件 1目录(设置为目录是 size要设置为0)
     * @param: blockList (文件的md5值) 可以把文件分为多个,然后分批上传
     * @return: java.lang.String
     */
    private static String create(String fileName, Long size, Integer isDir, String blockList) {
        //获取数据对象
        ConstantData instance = ConstantData.getInstance();
        String strURL = FILE_MANAGER_URL + "?method=create&access_token=" + instance.getATOKEN();
        String params = "path=" + APP_PATH + fileName + "&size=" + size + "&autoinit=1&block_list=[\"" + blockList + "\"]&isdir=" + isDir;
        return open(strURL, params, "GET");
    }

    /**
     * 阿丹 分片上传
     * @param: path 上传到百度网盘的地址
     * @param: uploadid 上传的id
     * @param: filePath 本地文件的地址
     * @return: java.lang.String
     */
    private static String upload(String path, String uploadid, File[] files) {
        //获取数据对象
        ConstantData instance = ConstantData.getInstance();
        try {

            for (int i = 0; i < files.length; i++) {
                String url = SLICING_UPLOAD_FILE_URL + "?method=upload" +
                        "&access_token=" + instance.getATOKEN() +
                        "&type=tmpfile&partseq=" + i +
                        "&path=" + path +
                        "&uploadid=" + uploadid;
                String s = sendFile(url, files[i]);
                log.info("正在上传分片文件{}{}", s, i);
            }

            return path;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 阿丹 预上传
     * @param: cloudPath 云端路径
     * @param: size 文件大小 字节
     * @param: isDir 0文件 1目录(设置为目录是 size要设置为0)
     * @param: blockList (文件的md5值) 可以把文件分为多个,然后分批上传
     * @return: java.lang.String
     */
    private static String precreate(String cloudPath, Long size, Integer isDir, String blockList) {
        //获取数据对象
        ConstantData instance = ConstantData.getInstance();
        String strURL = GET_READY_FILE_URL + "?method=precreate&access_token=" + instance.getATOKEN();
        String params = "path=" + cloudPath + "&size=" + size + "&autoinit=1&block_list=[\"" + blockList + "\"]&isdir=" + isDir;
        return open(strURL, params, "POST");
    }


    /**
     * 阿丹 获取md5值
     * String path 文件地址
     */
    private final static String[] strHex = {"0", "1", "2", "3", "4", "5",
            "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};

    private static String getMD5(File path) {
        StringBuilder buffer = new StringBuilder();
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] b = md.digest(org.apache.commons.io.FileUtils.readFileToByteArray(path));
            for (int value : b) {
                int d = value;
                if (d < 0) {
                    d += 256;
                }
                int d1 = d / 16;
                int d2 = d % 16;
                buffer.append(strHex[d1]).append(strHex[d2]);
            }
            return buffer.toString();
        } catch (Exception e) {
            return null;
        }
    }


    /**
     * 阿丹
     * @param: strURL 网址,可以是 http://aaa?bbb=1&ccc=2 拼接的
     * @param: params 拼接的body参数也就是form表单的参数  ddd=1&eee=2
     * @param: method 请求方式 get/post/put/delte等
     * @return: java.lang.String
     */
    private static String open(String strURL, String params, String method) {
        try {
            URL url = new URL(strURL);// 创建连接
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setDoOutput(true);
            connection.setDoInput(true);
            connection.setUseCaches(false);
            connection.setInstanceFollowRedirects(true);
            connection.setRequestMethod(method);
            connection.setRequestProperty("Accept", "application/json");// 设置接收数据的格式
            connection.setRequestProperty("Content-Type", "application/json");// 设置发送数据的格式
            connection.connect();
            OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream(), StandardCharsets.UTF_8);// utf-8编码
            out.append(params);
            out.flush();
            out.close(); // 读取响应
            int length = connection.getContentLength();// 获取长度
            InputStream is = connection.getInputStream();
            if (length != -1) {
                byte[] data = new byte[length];
                byte[] temp = new byte[512];
                int readLen = 0;
                int destPos = 0;
                while ((readLen = is.read(temp)) > 0) {
                    System.arraycopy(temp, 0, data, destPos, readLen);
                    destPos += readLen;
                }
                return new String(data, StandardCharsets.UTF_8);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 向指定 URL 发送POST方法的请求
     *
     * @param url   发送请求的 URL
     * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
     * @return 所代表远程资源的响应结果
     */
    public static String sendFile(String url, String param, String file) {
        if (url == null || param == null) {
            return url;
        }

        PrintWriter out = null;
        BufferedReader in = null;
        String result = "";
        try {
            URL realUrl = new URL(url);
            // 打开和URL之间的连接
            URLConnection conn = realUrl.openConnection();
            // 设置通用的请求属性
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent",
                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            //设置链接超时时间为2秒
            conn.setConnectTimeout(1000);
            //设置读取超时为2秒
            conn.setReadTimeout(1000);
            // 获取URLConnection对象对应的输出流
            out = new PrintWriter(conn.getOutputStream());
            out.write(file);
            // 发送请求参数
            out.print(param);
            // flush输出流的缓冲
            out.flush();
            // 定义BufferedReader输入流来读取URL的响应
            in = new BufferedReader(
                    new InputStreamReader(conn.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            System.out.println(e.getMessage() + "地址:" + url);
            return null;
        }
        //使用finally块来关闭输出流、输入流
        finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                System.out.println(ex.getMessage());
                return null;
            }
        }
        return result;
    }


    /**
     * @param: filePath
     * @param: unit 单个文件大小
     * @return: 返回文件的目录
     */
    private static File[] separate(Object obj, Integer unit) {

        try {

            InputStream bis = null;//输入流用于读取文件数据
            OutputStream bos = null;//输出流用于输出分片文件至磁盘
            File file = null;
            if (obj instanceof String) {
                file = new File((String) obj);
            }
            if (obj instanceof File) {
                file = (File) obj;
            }

            String filePath = file.getAbsolutePath();
            File newFile = new File(filePath.substring(0, filePath.lastIndexOf("\\") + 1));
            String directoryPath = newFile.getAbsolutePath();
            long splitSize = unit * 1024 * 1024;//单片文件大小,MB
            if (file.length() < splitSize) {
                log.info("文件小于单个分片大小,无需分片{}", file.length());
                return new File[]{file};
            }


            //分片一
            bis = new BufferedInputStream(new FileInputStream(file));
            long writeByte = 0;//已读取的字节数
            int len = 0;
            byte[] bt = new byte[1024];
            while (-1 != (len = bis.read(bt))) {
                if (writeByte % splitSize == 0) {
                    if (bos != null) {
                        bos.flush();
                        bos.close();
                    }
                    bos = new BufferedOutputStream(new FileOutputStream(filePath + "." + (writeByte / splitSize + 1) + ".part"));
                }
                writeByte += len;
                bos.write(bt, 0, len);
            }

            log.info("文件分片成功!");

            //排除被分片的文件
            if (newFile.isDirectory()) {
                File[] files = newFile.listFiles();
                File[] resultFiles = new File[files.length - 1];
                int j = 0;
                for (int i = 0; i < files.length; i++) {
                    if (!files[i].equals(file)) {
                        resultFiles[j] = files[i];
                        j++;
                    }
                }
                return resultFiles;
            }

            bos.flush();
            bos.close();
            bis.close();
            return new File[0];
        } catch (Exception e) {
            log.info("文件分片失败!");
            e.printStackTrace();
        }
        return null;
    }

    //splitNum:要分几片,currentDir:分片后存放的位置,subSize:按多大分片
    public static File[] nioSpilt(Object object, int splitNum, String currentDir, double subSize) {
        try {
            File file = null;
            if (object instanceof String) {
                file = new File((String) object);
            }
            if (object instanceof String) {
                file = (File) object;
            }
            FileInputStream fis = new FileInputStream(file);
            FileChannel inputChannel = fis.getChannel();
            FileOutputStream fos;
            FileChannel outputChannel;
            long splitSize = (long) subSize;
            long startPoint = 0;
            long endPoint = splitSize;
            for (int i = 1; i <= splitNum; i++) {
                fos = new FileOutputStream(currentDir + i);
                outputChannel = fos.getChannel();
                inputChannel.transferTo(startPoint, splitSize, outputChannel);
                startPoint += splitSize;
                endPoint += splitSize;
                outputChannel.close();
                fos.close();
            }
            inputChannel.close();
            fis.close();
            File newFile = new File(file.getAbsolutePath().substring(0, file.getAbsolutePath().lastIndexOf("\\") + 1));
            if (newFile.isDirectory()) {
                return newFile.listFiles();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new File[0];
    }

    /**
     * 阿丹 发送文件
     * @param: url 发送地址
     * @param: file 发送文件
     * @return: java.lang.String
     */
    private static String sendFile(String url, File file) {
        try {
            MultipartEntityBuilder builder = MultipartEntityBuilder.create();
            builder.setContentType(ContentType.MULTIPART_FORM_DATA);
            builder.addBinaryBody("file", file);
            String body = "";
            //创建httpclient对象
            CloseableHttpClient client = HttpClients.createDefault();
            //创建post方式请求对象
            HttpPost httpPost = new HttpPost(url);
            //设置请求参数
            HttpEntity httpEntity = builder.build();
            httpPost.setEntity(httpEntity);
            //执行请求操作,并拿到结果(同步阻塞)
            CloseableHttpResponse response = client.execute(httpPost);
            //获取结果实体
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                //按指定编码转换结果实体为String类型
                body = EntityUtils.toString(entity, "utf-8");
            }
            EntityUtils.consume(entity);
            //释放链接
            response.close();
            return body;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


}

如果其他问题可以留言联系我。 

  • 6
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 34
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 34
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值