ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[记录点滴]在Ionic和Android中上传Blob图片

2021-04-26 11:58:14  阅读:210  来源: 互联网

标签:end err -- Blob file Android Ionic local


[记录点滴]在Ionic和Android中上传Blob图片


目录


0x00 摘要

本文是开发中的简略记录,具体涉及知识点有:Blob,Ionic,Android和Lua。

起因是因为刚刚看到一篇关于Blob的文章你不知道的 Blob ,突然回忆起来在开发过程中也曾经使用过这种图片,所以就翻了翻代码,整理记录下来。

0x01 Blob

Blob(Binary Large Object)表示二进制类型的大对象,通常是影像、声音或多媒体文件。MySql/Oracle数据库中,就有一种Blob类型,专门存放二进制数据。

在 JavaScript 中 Blob 对象表示一个不可变、原始数据的类文件对象,它不一定非得是大量数据,也可以表示一个小型文件的内容。另外,JavaScript 中的 File 接口是基于 Blob,继承 Blob 的功能并将其扩展使其支持用户系统上的文件。

Blob 由一个可选字符串 type 和 blobParts 组成,其中, type 通常为 MIME 类型。

MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型,常见有:超文本标记语言文本 .html text/html 、PNG图像 .png image/png 、普通文本 .txt text/plain  等。

0x02 项目简述

项目涉及方面比较多,有Ionic,Android,ios,后台处理图片部分是Lua。客户端需要上传小图片到后台。因为ios中上传图片这部分我没有参与,所以略过。

以下代码做了简略和转换。

0x02 Ionic

Ionic上传过程中,主要使用Promise做异步控制,用$http做上传处理。

function uploadPicture(file) {
      var q = $q.defer();
      var url = .....;
      var data = new FormData();
      var ext = file.split(',')[0].split(':')[1].split(';')[0].split('/')[1];
      data.append("file", dataURItoBlob(file), "picture." + ext); // 调了半天原来是这里Blob要加个name
      $http.post(url, data, {
          params: {
            token: getToken()
          },
          transformRequest: angular.identity,
          headers: {
            'Content-Type': undefined
          }
        })
        .success(function(result) {
          q.resolve(result);
        })
        .error(function(err) {
          q.reject(err);
        });
      return q.promise;
}

base64字符串转图片格式的函数在这里

function dataURItoBlob(dataURI) {
    // convert base64/URLEncoded data component to raw binary data held in a string
    var byteString;
    if (dataURI.split(',')[0].indexOf('base64') >= 0)
      byteString = atob(dataURI.split(',')[1]);
    else
      byteString = unescape(dataURI.split(',')[1]);

    // separate out the mime component
    var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];

    // write the bytes of the string to a typed array
    var ia = new Uint8Array(byteString.length);
    for (var i = 0; i < byteString.length; i++) {
      ia[i] = byteString.charCodeAt(i);
    }
    return new Blob([ia], {
      name: 'picture',
      type: mimeString
    });
}

0x03 Android

网络传输使用了retrofit2。

public void uploadAvatar(Observerobserver, int userId, String filePath) {
        checkOauth();
        File file = new File(filePath);
        RequestBody requestBody = RequestBody.create(MediaType.parse("image/*"), file);
        MultipartBody.Part body = MultipartBody.Part.createFormData("file", file.getName(), requestBody);

        networkService.uploadAvatar(userId, body)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(observer);
    }

// 这里是NetworkService实现
@Multipart
@POST(Constants.Url + "{id}")
ObservableuploadAvatar(@Path("id") int id, @Part MultipartBody.Part file);

0x04 Lua

后台中图片接口是用Lua来处理。

res, err = REQUEST.get_upload_file()
if _.isEmpty(res) then
     ngx.say(RESPONSE.error(-1, err, 404))
end

当时参考了解决nginx + lua 上传文件问题。对原文代码做了修改以匹配我们实际环境。

-- 注意lua-resty-upload模块只能上传有boundary的post请求体,没有boundary的话需要使用socket来进行传输。
local UPLOAD = require "resty.upload"

function _M.get_upload_file() 
    local chunk_size = 4096  --如果不设置默认是4096.
    local form,err = UPLOAD:new(chunk_size)
    local sha1 = RESTY_SHA1:new()  --测试时可以用来verify
    local file
    local filelen=0
    local filename
    local osfilepath = CONF.const()['UPLOAD_FILE_PATH']     
    local i=0
    local response 

    if not _.isEmpty(err) then
        ngx.log(LOGGER.e("form is: ", form, ", err is: ", err))
    end

    form:set_timeout(0) -- form:set_timeout(1000) -- 1 sec

    while true do
        local typ, res, err = form:read()        
        if not typ then
            ngx.log(LOGGER.e("failed to read: ", err))
            return false
        end

        if typ == "header" then
            if res[1] ~= "Content-Type" and res[1] ~= "Content-Length" then -- 对比原文增加了一个判断
                filename = get_filename(res[2])
                if filename then
                    i=i+1
                    filepath = osfilepath .. filename
                    file = io.open(filepath,"wb+") -- 对比原文增加了b
                    if not file then
                        ngx.log(LOGGER.e("failed to open file "))
                        return false
                    end
                else
                end
            end
        elseif typ == "body" then
            if file then
                filelen= filelen + tonumber(string.len(res))    
                file:write(res)
                sha1:update(res) -- verify in dev env
            else
            end
        elseif typ == "part_end" then
            if file then
                file:close()
                file = nil
                ngx.say("file upload success")
                local sha1_sum = sha1:final() -- verify in dev env
                sha1:reset()
            end
        elseif typ == "eof" then
            break
        else
            -- do nothing
        end
    end
    if i==0 then
        ngx.log(LOGGER.e("please upload at least one file!"))
        return false
    end

    response = {
        result = true, 
        fn = filename, 
        fp = filepath
    }
    return response
end

0x05 参考

你不知道的 Blob

解决nginx + lua 上传文件问题

标签:end,err,--,Blob,file,Android,Ionic,local
来源: https://blog.51cto.com/u_15179348/2734159

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有