zoukankan      html  css  js  c++  java
  • [记录点滴]在Ionic和Android中上传Blob图片

    [记录点滴]在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(Observer<Response> observer, 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}")
    Observable<Response> uploadAvatar(@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 上传文件问题

  • 相关阅读:
    Read-Copy Update Implementation For Non-Cache-Coherent Systems
    10 华电内部文档搜索系统 search04
    10 华电内部文档搜索系统 search05
    lucene4
    10 华电内部文档搜索系统 search01
    01 lucene基础 北风网项目培训 Lucene实践课程 索引
    01 lucene基础 北风网项目培训 Lucene实践课程 系统架构
    01 lucene基础 北风网项目培训 Lucene实践课程 Lucene概述
    第五章 大数据平台与技术 第13讲 NoSQL数据库
    第五章 大数据平台与技术 第12讲 大数据处理平台Spark
  • 原文地址:https://www.cnblogs.com/rossiXYZ/p/13123677.html
Copyright © 2011-2022 走看看