华为云OBS对象存储取消下载

背景

车机座舱开发会有远程OTA的需求,多数国产审计的镜像会选择将升级文件存储到华为云OBS对象存储中,然后车机通过一些列验证下载到进行升级。
由于车机流量都是计量收费,动则上G的系统镜像在使用中尤其需要节省。于是有了再下载过程中取消从OBS中下载的要求,但是通过查询文档,发现华为云给出的demo和文档中并没有给出车机android系统的中通取消下载的方法或者示例。
华为文档:https://support.huaweicloud.com/sdk-android-devg-obs/obs_26_0509.html

工单咨询回复

工单截图
客服提到的参考(实际没有意义):https://obssdk.obs.cn-north-1.myhuaweicloud.com/apidoc/cn/java/index.html
客服给出的方式是中断下载线程

代码实现

import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;

import androidx.annotation.NonNull;

import com.obs.services.ObsClient;
import com.obs.services.ObsConfiguration;
import com.obs.services.exception.ObsException;
import com.obs.services.model.DownloadFileRequest;
import com.obs.services.model.DownloadFileResult;
import com.obs.services.model.ProgressListener;
import com.obs.services.model.ProgressStatus;
import com.tyw.vb2.ota.callback.IDownLoadCallback;
import com.tyw.vb2.ota.entity.SecretEntiy;
import com.tyw.vb2.ota.util.FileUtils;

import java.io.File;
import java.io.IOException;


/**
 * Created by Android Studio.
 * Date: 2023/8/15
 * Time: 19:53
 * description:华为obs下载
 */
public class DownloadHelper {

    private static final String TAG = "DownloadHelper";


    private static DownloadHelper sInstance;
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            if (msg.what == 1) {
                //发送进度
                String taskNum = (String) msg.obj;
//can发送进度                ResponseHelper.getInstance().sendDownProgress(taskNum, currentProgress);
                Message message = Message.obtain();
                message.what = 1;
                message.obj = taskNum;
                handler.sendMessageDelayed(message, PROGRESS_WAIT_TIME);
            }
        }
    };


    public  final String LOCAL_DOWNLOAD_PAHT = "/sdcard/";
    // Endpoint以北京四为例,其他地区请按实际情况填写。
    private   String endPoint = "https://obs.cn-north-4.myhuaweicloud.com";
    private  String bucketname = "桶名";
    private  String objectname = "对象名";
    private String ak = "秘钥";
    private String sk = "秘钥";


    /**
     * 下载进度
     */
    private int currentProgress = 0;
    private String currentTaskNum = null;
    private AsyncTask asyncTask;
    private ObsClient obsClient = null;
    private DownloadFileRequest request = null;

    public static DownloadHelper getInstance() {
        if (sInstance == null) {
            sInstance = new DownloadHelper();
        }
        return sInstance;
    }


    public void downObject(String taskNum, String reqPath, IDownLoadCallback callback) {
        Log.i(TAG, taskNum + "-新下载任务--》" + reqPath);
        if (currentTaskNum != null) {
            Log.w(TAG, "正在下载中,取消新任务");
            //正在下载,取消任务
            return;
        }
        this.currentTaskNum = taskNum;
        if (!IS_DEBUG) {
            SecretEntiy secretEntiy = FileUtils.readSerect();
            ak = secretEntiy.getAk();
            sk = secretEntiy.getSk();
            bucketname = getBucketname(reqPath);
            objectname = getObjectName(reqPath);
        }

        if (TextUtils.isEmpty(ak) || TextUtils.isEmpty(sk)) {
            Log.e(TAG, "ak或者sk为空");
            ResponseHelper.getInstance().sendkeyError(taskNum, ResponseHelper.obsKeyErrorEnum.AK_SK_NULL);
            return;
        }


        asyncTask = new AsyncTask<Void, Integer, File>() {
            @Override
            protected File doInBackground(Void... voids) {
                File file = downOBS(bucketname, objectname);
                return file;
            }

            @Override
            protected void onPostExecute(File file) {
                super.onPostExecute(file);
                if (file != null && callback != null) {
                    Log.i(TAG, "文件下载成功-->" + file.getPath());
                    callback.onSuccess(file);
                }
            }

            @Override
            protected void onCancelled() {
                Log.i(TAG, "异步下载任务终止");
                super.onCancelled();
            }
        }.execute();
    }

    /**
     * 下载
     *
     * @param bucketname
     * @param objectName 错误码:https://support.huaweicloud.com/usermanual-obs/obs_03_0348.html
     * @return
     */
    private File downOBS(String bucketname, String objectName) {
        File file = null;
        if (FileUtils.isFileExist(LOCAL_DOWNLOAD_PAHT + objectName)) {
            Log.i(TAG, "删除历史文件--》" + objectName);
            FileUtils.deleteFile(LOCAL_DOWNLOAD_PAHT + objectName);
        }

        currentProgress = 0;
        // 创建ObsClient实例
        ObsConfiguration config = new ObsConfiguration();
        config.setSocketTimeout(60 * 1000);
        config.setConnectionTimeout(60 * 1000);
        config.setEndPoint(endPoint);
        obsClient = new ObsClient(ak, sk, config);
        DownloadFileRequest request = new DownloadFileRequest(bucketname, objectName);
// 设置下载对象的本地文件路径
        request.setDownloadFile(LOCAL_DOWNLOAD_PAHT + objectName);
// 设置分段下载时的最大并发数
        request.setTaskNum(3);
// 设置分段大小为100MB
        request.setPartSize(100 * 1024 * 1024);
// 开启断点续传模式
        request.setEnableCheckpoint(true);
        request.setProgressListener(new ProgressListener() {
            @Override
            public void progressChanged(ProgressStatus status) {
                Log.d(TAG, "obs下载进度-》" + status.getTransferPercentage());
                currentProgress = status.getTransferPercentage();
            }
        });

        Message msg = Message.obtain();
        msg.what = 1;
        msg.obj = currentTaskNum;
        handler.sendMessageDelayed(msg, PROGRESS_WAIT_TIME);
        try {
            // 进行断点续传下载
            DownloadFileResult result = obsClient.downloadFile(request);

            Log.d(TAG, "华为云Metadata:" + result.getObjectMetadata());
            file = new File(LOCAL_DOWNLOAD_PAHT + objectName);
            if (file != null) {
                ResponseHelper.getInstance().sendDownFinish(currentTaskNum);
            }
        } catch (ObsException e) {
        //can异常上报
            file = null;

            Log.e(TAG, e.getErrorCode() + "-Error Code==>" + e.getResponseCode());
            Log.e(TAG, e.getErrorHostId() + "-Error message-->" + e.getMessage());
           
            if (e.getResponseCode() == -1 && !TextUtils.isEmpty(e.getMessage())) {
                //无法解析服务器
                Log.e(TAG, "wifi无法访问互联网");
                ResponseHelper.getInstance().sendDownError(currentTaskNum, ResponseHelper.DownErrorEnum.NOT_WIFI);
            } else if ("SignatureDoesNotMatch".equals(e.getErrorCode())) {
                //鉴权秘钥已过期
                ResponseHelper.getInstance().sendkeyError(currentTaskNum, ResponseHelper.obsKeyErrorEnum.AK_SK_ERROR);
            } else if ("RequestTimeout".equals(e.getErrorCode())) {
                //超时                ResponseHelper.getInstance().sendDownError(currentTaskNum, ResponseHelper.DownErrorEnum.REQUEST_TIME_OUT);
            }
            e.printStackTrace();
        } finally {
            Log.i(TAG, "DOWN FINALLY");
            this.currentTaskNum = null;
            handler.removeMessages(1);
            try {
                if (obsClient != null) {
                    obsClient.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return file;

    }

    private String getObjectName(String reqParams) {
        SecretEntiy secretEntiy = FileUtils.readSerect();
        String objectName = reqParams.split(";")[1] + "/" + secretEntiy.getVin() + "-" + secretEntiy.getTboxid();
        Log.i(TAG, "需要下载的objectName-->" + objectName);
        return objectName;
    }

    private String getBucketname(String reqParams) {
        return reqParams.split(";")[0];
    }

    /**
     * 取消下载
     *
     * @param taskNum
     */
    public void cancle(String taskNum) {
        if (!TextUtils.isEmpty(taskNum) && taskNum.equals(currentTaskNum) && obsClient != null) {
            Log.w(TAG, "取消下载--》" + taskNum);
            handler.removeMessages(1);
            if (asyncTask != null) {
                asyncTask.cancel(true);
            }
            this.currentTaskNum = null;
        }
    }
}

提示

由于项目比较着急,代码是用android已经淘汰的AsyncTask编写的,由于华为给出的异常反馈并没有包含can数据给出的错误反馈,所以异常部分判断的也很不规范,并且代码没有优化。各位看官有更好的代码实现,欢迎回复指正。谢谢!

  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
华为云OBS提供了分段下载的功能,允许用户将大文件分成多个部分进行下载,从而提高下载效率并节省带宽和时间。华为云OBS分段下载的实现方式是通过HTTP协议的Range头信息来实现的。用户可以通过设置Range头信息中的起始位置和结束位置来指定需要下载的文件片段,服务器将只返回指定片段的数据给用户。 具体实现分段下载的方法如下: 1. 首先,你需要使用Java语言编写代码来实现华为云OBS文件的下载功能。你可以使用华为云OBS的Java SDK来简化操作。可以参考中的Java华为云OBS文件上传下载工具类来实现下载功能。 2. 使用华为云OBS的Java SDK,你可以通过设置GetObjectRequest对象的range属性来指定需要下载的文件片段的范围。例如,你可以设置range为"0-1023"表示只下载文件的前1024个字节,或者设置range为"1024-"表示从第1024个字节开始的所有数据。 3. 通过调用OBSClient的getObject方法并传入GetObjectRequest对象来发送下载请求。服务器将返回指定片段的数据给用户。 需要注意的是,华为云OBS分段下载功能需要服务器端支持,具体支持的范围大小可能会有限制。在使用分段下载功能时,建议参考华为云OBS的官方文档以了解更多详细信息和限制。 总结起来,华为云OBS提供了分段下载的功能,用户可以通过设置HTTP协议的Range头信息来指定需要下载的文件片段,服务器将只返回指定片段的数据给用户。使用Java语言可以通过华为云OBS的Java SDK来实现分段下载功能。具体的实现方法可以参考中的Java华为云OBS文件上传下载工具类。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [图片批量上传至服务器/华为云obs 前台采用webuploader.js div+css布局 图片.zip华为云obs浏览器下载](https://blog.csdn.net/m0_54930214/article/details/127985386)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [华为云OBS文件上传下载工具类](https://blog.csdn.net/weixin_45285213/article/details/125596661)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [华为云obs参考代码以及demo](https://download.csdn.net/download/qq_38707432/10548349)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

写点啥呢

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

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

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

打赏作者

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

抵扣说明:

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

余额充值