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

丈夫欲遂平生志,一载寒窗一举汤。这篇文章主要讲述[记录点滴]在Ionic和Android中上传Blob图片相关的知识,希望能为你提供帮助。
[记录点滴]在Ionic和android中上传Blob图片目录

  • [记录点滴]在Ionic和Android中上传Blob图片
    • 0x00 摘要
    • 0x01 Blob
    • 0x02 项目简述
    • 0x02 Ionic
    • 0x03 Android
    • 0x04 Lua
    • 0x05 参考

0x00 摘要本文是开发中的简略记录,具体涉及知识点有:Blob,Ionic,Android和Lua。
起因是因为刚刚看到一篇关于Blob的文章你不知道的 Blob ,突然回忆起来在开发过程中也曾经使用过这种图片,所以就翻了翻代码,整理记录下来。
0x01 BlobBlob(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 IonicIonic上传过程中,主要使用Promise做异步控制,用$http做上传处理。
function uploadPicture(file) { var q = $q.defer(); var url = .....; var data = https://www.songbingjia.com/android/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)) endform:set_timeout(0) -- form:set_timeout(1000) -- 1 secwhile true do local typ, res, err = form:read() if not typ then ngx.log(LOGGER.e(" failed to read: " , err)) return false endif 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 endresponse = { result = true, fn = filename, fp = filepath } return response end

0x05 参考你不知道的 Blob
【[记录点滴]在Ionic和Android中上传Blob图片】解决nginx + lua 上传文件问题

    推荐阅读