利用Alist代理百度网盘,提出一种新的对象存储方式(附Java代码)

一、现有存储的一般方案

对象存储方案大比拼——本地存储、OSS、MinIO、Ceph、Apache Ozone 与 OpenIO-优快云博客

二、为什么要用百度网盘作代理

1.免费;

2.安全;

3.云部署,不用考虑本地跑和部署后移植文件的问题;

三、适用于

1.个人开发者;

2.不想充钱;

3.本地内存不够的;

4.服务器内存不够的

四、解决什么问题

1.文件如果存储在本地,则部署到服务器上的时候跨系统会出现问题;文件如果存储在后端系统中,则部署到服务器时内存会非常大从而导致系统响应速度慢、内存泄露等问题;

2.百度网盘只允许企业注册应用,不允许个人注册;

3.服务器内存有限,NAS存储要钱;

五、解决方案

通过Alist代理百度网盘,基于Alist开放的文档,撰写一套Java代码。

六、Alist配置百度网盘文档

百度网盘 | AList文档

七、Alist的API文档

在线调试 | AList文档

八、代码

1.实体类

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class AlistConfig {
    private String alistBaseUrl;
    private String alistUsername;
    private String alistPassword;
}

2.HTTP请求

import com.google.gson.Gson;
import okhttp3.*;

import java.io.IOException;
import java.util.Map;

public class OkHttpUtils {
    private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
    private static final OkHttpClient client = new OkHttpClient();

    /**
     * 发送 POST 请求
     *
     * @param url      请求地址
     * @param bodyData 请求体数据,可以是 Map 或 JSON 字符串
     * @return 响应结果
     */
    public static String doPost(String url, Object bodyData) {
        RequestBody requestBody;
        if (bodyData instanceof Map) {
            requestBody = RequestBody.create(JSON, new Gson().toJson(bodyData));
        } else if (bodyData instanceof String) {
            requestBody = RequestBody.create(JSON, (String) bodyData);
        } else {
            throw new IllegalArgumentException("请求参数必须是Map或JSON");
        }
        Request request = new Request.Builder()
                .url(url)
                .post(requestBody)
                .build();
        try (Response response = client.newCall(request).execute()) {
            if (response.isSuccessful()) {
                return response.body().string();
            } else {
                throw new IOException("错误代码:" + response);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static String doPostWithHeaders(String url, Object bodyData, Map<String, String> headers) {
        RequestBody requestBody;
        if (bodyData instanceof Map) {
            requestBody = RequestBody.create(JSON, new Gson().toJson(bodyData));
        } else if (bodyData instanceof String) {
            requestBody = RequestBody.create(JSON, (String) bodyData);
        } else {
            throw new IllegalArgumentException("请求参数必须是Map或JSON");
        }
        Request request = new Request.Builder()
                .url(url)
                .post(requestBody)
                .build();
        for (Map.Entry<String, String> entry : headers.entrySet()) {
            request = request.newBuilder().addHeader(entry.getKey(), entry.getValue()).build();
        }
        try (Response response = client.newCall(request).execute()) {
            if (response.isSuccessful()) {
                return response.body().string();
            } else {
                throw new IOException("错误代码:" + response);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

3.Alist工具类

ram path 路径 eg: /files/test/xxx.txt
     * @param password 文件密码,可以传空字符串
     * @return
     */
    public static String getAlistFileInfo(AlistConfig alistConfig,String path,String password){
        String url = alistConfig.getAlistBaseUrl() + "/api/fs/get";
        HashMap<String, String> headerData = new HashMap<>();
        HashMap<String, String> bodyData = new HashMap<>();
        bodyData.put("path", path);
        bodyData.put("password", password);
        headerData.put("Authorization", getToken(alistConfig));
        return OkHttpUtils.doPostWithHeaders(url, bodyData, headerData);
    }

    /**
     * 递归-遍历文件夹下所有文件下载地址
     * @param alistConfig alist配置实体类
     * @param path 目录 eg:/files/test
     * @param password 文件密码,可以传空字符串
     * @return {path : rawUrl}
     */
    public static ArrayList<HashMap<String, String>> getAlistAllFilesInfo(AlistConfig alistConfig,String path, String password) {
        // 获取path目录下信息
        String result = getAlistFileList(alistConfig,path);
        // 获取所有的信息
        JSONObject json_data = JSON.parseObject(JSON.parseObject(result).get("data").toString());
        // 将content转为json数组
        JSONArray json_array = json_data.getJSONArray("content");

        ArrayList<HashMap<String, String>> filesInfoMaps = new ArrayList<>();
        processDirectory(alistConfig,filesInfoMaps, path,  json_array, password);
        return filesInfoMaps;

    }

    //处理文件夹
    private static void processDirectory(AlistConfig alistConfig,ArrayList<HashMap<String, String>> filesInfoMaps, String path, JSONArray json_array, String password) {
        //判空处理
        if (json_array == null || json_array.isEmpty()) {
            return;
        }
        for (int i = 0; i < json_array.size(); i++) {
            HashMap<String, String> filesInfoMap = new HashMap<>();
            // 获取当前json对象
            JSONObject json_object = json_array.getJSONObject(i);
            // 获取当前json对象的name
            String name = json_object.getString("name");
            // 判断是否为文件夹
            String is_dir = json_object.getString("is_dir");
            if (!"true".equals(is_dir)) {
                String filename = safePathJoin(path, name);
                String alistFileInfo = getAlistFileInfo(alistConfig,filename, password);
                JSONObject json_file_data = JSON.parseObject(JSON.parseObject(alistFileInfo).get("data").toString());
                if (json_file_data.containsKey("content")) {
                    JSONArray json_file_content = json_file_data.getJSONArray("content");
                    for (int j = 0; j < json_file_content.size(); j++) {
                        // 获取当前json对象
                        JSONObject json_file_object = json_file_content.getJSONObject(j);
                        // 获取当前json对象的raw_url
                        String rawUrl = json_file_object.getString("raw_url");
                        filesInfoMap.put("filePath",filename);
                        filesInfoMap.put("rawUrl",rawUrl);
                        filesInfoMaps.add(filesInfoMap);
                    }
                } else {
                    String rawUrl = json_file_data.getString("raw_url");
                    filesInfoMap.put("filePath",filename);
                    filesInfoMap.put("rawUrl",rawUrl);
                    filesInfoMaps.add(filesInfoMap);
                }
            } else {
                // 处理文件夹
                String directoryPath = safePathJoin(path, name);
                String directoryResult = getAlistFileList(alistConfig,directoryPath);
                JSONObject directoryJsonData = JSON.parseObject(JSON.parseObject(directoryResult).get("data").toString());
                JSONArray directoryJsonArray = directoryJsonData.getJSONArray("content");
                processDirectory(alistConfig,filesInfoMaps, directoryPath, directoryJsonArray, password);
            }
        }
    }

    private static String safePathJoin(String base, String name) {
        // 防止路径穿越
        return base.endsWith("/") ? base + name : base + "/" + name;
    }



    /**
     * 上传文件
     * @param alistConfig alist配置实体类
     * @param originalPath 目标文件
     * @param targetPath 目的路径
     * @param FileName 目的文件名
     * @return 文件路径/结果
     * @throws IOException
     */
    public static String uploadFile(AlistConfig alistConfig,String originalPath,String FileName,String targetPath) throws IOException {
        String url = alistConfig.getAlistBaseUrl() + "/api/fs/put";
        OkHttpClient client = new OkHttpClient().newBuilder()
                .build();
        MediaType mediaType = MediaType.parse("text/plain");
        byte[] bytes = Files.readAllBytes(Paths.get(originalPath));
        RequestBody body = RequestBody.create(mediaType, bytes);
        Request request = new Request.Builder()
                .url(url)
                .method("PUT", body)
                .addHeader("Authorization", getToken(alistConfig))
                .addHeader("File-Path", targetPath+"/"+FileName)
                .addHeader("As-Task", "true")
                .addHeader("Content-Length", "")
                .build();
        Response response = client.newCall(request).execute();
        JSONObject parse = JSON.parseObject(response.body().string());
        if (parse.get("code").toString().equals("200")){
            return alistConfig.getAlistBaseUrl()+"/d"+targetPath+"/"+FileName;
        }else {
            return parse.get("message").toString();
        }
    }

}

4.测试类


import com.mavis.entity.AlistConfig;
import com.mavis.util.AlistUtils;

import java.util.ArrayList;
import java.util.HashMap;

public class Test {
    public static void main(String[] args) {
        AlistConfig alistConfig = new AlistConfig(
                "http://你的服务器地址:5244",
                "你的账号名",
                "你的密码"
        );
        ArrayList<HashMap<String, String>> alistAllFilesInfo = AlistUtils.getAlistAllFilesInfo(alistConfig, "/BaiduDisk/AlistStorage/pic", "");
        for (HashMap<String, String> map : alistAllFilesInfo) {
            System.out.println(map);
        }


    }
}

九、AlistUtils使用说明

1.初始化AlistConfig对象 (所有方法的前提)

AlistConfig alistConfig = new AlistConfig("http://localhost:5244","admin","123456");
//传入alist地址,用户名,密码即可

2.获取指定目录下列表

String alistFileList = AlistUtils.getAlistFileList(alistConfig, "/files/test");
//传入实例化的AlistConfig对象和路径即可

3.获取指定文件信息

String alistFileInfo = AlistUtils.getAlistFileInfo(alistConfig, "/files/test/test.txt", "");
//传入实例化的AlistConfig对象、路径以及文件密码即可 文件密码若没设置可以为空

4.递归获取指定目录下所有文件的下载直链

ArrayList<HashMap<String, String>> alistAllFilesInfo = AlistUtils.getAlistAllFilesInfo(alistConfig, "/files/test", "");
//传入实例化的AlistConfig对象、路径以及文件密码即可 文件密码若没设置可以为空
//返回的ArrayList集合中会包含所有的文件对应路径以及下载地址的键值对集合

5.上传文件

AlistUtils.uploadFile(alistConfig, "D:/files/test/test.txt", "/files/test/test","test.txt");
//传入实例化的AlistConfig对象、源文件、目标目录、传入后文件名
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

深山老林.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值