当前位置: 首页 > article >正文

Android上传到Minio本地存储

  1. Minio简介
    MinIO是一个对象存储解决方案,它提供了与Amazon Web Services S3兼容的API,并支持所有核心S3功能。 MinIO有能力在任何地方部署 - 公有云或私有云,裸金属基础设施,编排环境,以及边缘基础设施。author: https://blog.csdn.net/keeng2008

  2. 引入第三方库

implementation 'com.amazonaws:aws-android-sdk-s3:2.76.0'
implementation 'com.amazonaws:aws-android-sdk-mobile-client:2.76.0'
  1. 获取认证信息,创建Client对象
    创建对象时需要认证信息,需要有{AccessKeyId,SecretKey, SessionToken, endpoint}, 有些临时使用的情况,只需要{AccessKeyId,SecretKey, endpoint}。
    认证信息有有效期的,最好通过即时请求本地服务器,获得以上认证信息,缓存10分钟后丢弃。
        val region = Region.getRegion(Regions.CN_NORTH_1)
        val credentials = object : AWSSessionCredentials {
            override fun getAWSAccessKeyId(): String {
                return cfg.AccessKeyId
            }

            override fun getAWSSecretKey(): String {
                return cfg.AccessKeySecret
            }

            override fun getSessionToken(): String {
                return cfg.SecurityToken
            }
        }
        val s3: AmazonS3 = AmazonS3Client(credentials, region, ClientConfiguration());
        //服务器地址
        s3.setEndpoint(cfg.endpoint);

其中的endpoint为minio服务器地址,如 http://172.18.18.8:10100, 该端口跟网页上使用的不一样,否则会提示该端口不支持上传。

  1. 上传文件PutObjectRequest
    minio服务器中需要创建一个BUCKET,作为存储文件的空间。如 BUCKET = “demo_cloud”
        val totalBytesLength = file.length()
        val objectKey = relativePath + fileName
        val transferedbytes = AtomicLong(0)
        val res: PutObjectResult = s3.putObject(PutObjectRequest(BUCKET, objectKey, file)
            .withGeneralProgressListener { progressEvent ->
                val trans = transferedbytes.addAndGet(progressEvent.bytesTransferred)
                // 回调通知上传的进度
                progressCallback.onProgress(totalBytesLength, trans)
            });
        val map = mutableMapOf<String, Any>()
        map.put("eTag", res.eTag);
        map.put("objectKey", objectKey)
        return map

对于一般文件都能上传成功了,然后发现大文件时会报错,因为它对文件大小contentLenght使用int类型的参数,也就是超过2^31(大约1.9G)的文件会报错,无法传输;这时就需要使用分段上传了。

  1. 大文件分段上传MultipartUpload

反正都要写分段上传了,那就大于500MB的文件都使用分段上传吧-

    val SIZE_1M_BYTE: Long = 1024 * 1024
    if (totalBytesLength > SIZE_1M_BYTE * 500) {
        return uploadWithMultipart(s3, file, objectKey, progressCallback)
    } 

    private suspend fun uploadWithMultipart(
        s3Client: AmazonS3, file: File,
        objectKey: String, progressCallback: IUploadClient.UploadCallback
    ): Map<String, Any> {
        Log.i(TAG, "uploadWithMultipart file: $file")
        val contentLength = file.length()
        var partSize = CommonUtils.SIZE_1M_BYTE * 20 // Set part size to 20 MB.


        // Create a list of ETag objects. You retrieve ETags for each object part
        // uploaded,
        // then, after each individual part has been uploaded, pass the list of ETags to
        // the request to complete the upload.
        val partETags = mutableListOf<PartETag>()

        // Initiate the multipart upload.
        val initRequest = InitiateMultipartUploadRequest(BUCKET, objectKey)
        val initResponse: InitiateMultipartUploadResult =
            s3Client.initiateMultipartUpload(initRequest)

        // Upload the file parts.
        var filePosition: Long = 0
        var i = 1
        while (filePosition < contentLength) {

            // Because the last part could be less than 5 MB, adjust the part size as
            // needed.
            partSize = Math.min(partSize, contentLength - filePosition)

            // Create the request to upload a part.
            val uploadRequest: UploadPartRequest = UploadPartRequest()
                .withBucketName(BUCKET)
                .withKey(objectKey)
                .withUploadId(initResponse.getUploadId())
                .withPartNumber(i)
                .withFileOffset(filePosition)
                .withFile(file)
                .withPartSize(partSize)

            // Upload the part and add the response's ETag to our list.
            val uploadResult: UploadPartResult = s3Client.uploadPart(uploadRequest)
            partETags.add(uploadResult.getPartETag())
            filePosition += partSize
            i++

            progressCallback.onProgress(contentLength, filePosition)
            delay(120L)
        }

        // Complete the multipart upload.
        val compRequest = CompleteMultipartUploadRequest(
            BUCKET, objectKey,
            initResponse.getUploadId(), partETags
        )
        val res: CompleteMultipartUploadResult = s3Client.completeMultipartUpload(compRequest)
        val map = mutableMapOf<String, Any>()
        map.put("eTag", res.eTag);
        map.put("objectKey", objectKey)
        return map
    }   

本文author: https://blog.csdn.net/keeng2008
文件传输都是非常耗时的过程,分段的中途让它delay休息一下,调用put之后会堵塞当前线程的,最好都放要在IO线程完成。


http://www.kler.cn/a/445689.html

相关文章:

  • React系列(八)——React进阶知识点拓展
  • WIN10拖入文件到桌面,文件自动移动到左上角,导致桌面文件错乱
  • day5,数据结构,单向,双向,循环链表
  • 行政管理痛点解决方案:OA系统助力企业提效减负
  • linux----系统i/o
  • Python-存储数据-Thu-Fri
  • php学习资料分享
  • U-Boot的编译与烧写
  • vue el-dialog实现可拖拉
  • RabbitMQ全局流量控制
  • 基于字节大模型的论文翻译(含免费源码)
  • CPU性能优化-磁盘空间和解析时间
  • 谷歌浏览器的扩展市场使用指南
  • 共享模型之无锁(乐观锁,CAS,原子类,LongAdder)
  • postman-9.12.2–安装包及汉化
  • 轨迹优化 | 基于Savitzky-Golay滤波的无约束路径平滑(附ROS C++/Python仿真)
  • OpenGL ES 01 渲染一个四边形
  • [Unity]【图形渲染】【游戏开发】Shader数学基础4-更多矢量运算
  • PC寄存器(Program Counter Register)jvm
  • 2024年云计算的发展趋势如何?
  • 【图像处理lec7】图像恢复、去噪
  • SSM 框架结合 Vue 实现电脑测评系统:助力用户明智选择
  • 在M系列芯片的Mac上使用Uniapp开发的依赖安装指南
  • 裸金属服务器的作用都有哪些?
  • GitHub年度报告发布!Python首次超越JavaScript
  • 高校教师成果管理小程序的设计与实现springboot+论文源码调试讲解