[记录点滴]在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 上传文件问题

[记录点滴]在Ionic和Android中上传Blob图片的更多相关文章

  1. .net项目中上传大图片失败

    .net项目中有时用户提出要上传大图片,一张图片有可能十几兆,本来用的第三方的上传控件,有限制图片上传大小的设置,以前设置的是2M.按照用户的要求,以为直接将限制图片上传大小的设置改下就可以了,但是当 ...

  2. .net项目中上传的图片或者文件太大 无法上传

    最近做项目的时候  用户提出要上传大图片  一张图片有可能十几兆  本来用的第三方的上传控件  有限制图片上传大小的设置 以前设置的是2M  按照用户的要求  以为直接将限制图片上传大小的设置改下就可 ...

  3. TP中上传文件图片的实现

    GoodsController.class.php控制器页面<?php namespace Admin\Controller; use Think\Controller; class Goods ...

  4. 【应用服务 App Service】App Service中上传文件/图片(> 2M)后就出现500错误(Maximum request length exceeded).

    问题描述 在使用App Service (Windows)做文件/图片上传时候,时常遇见上传大文件时候出现错误,这是因为IIS对文件的大小由默认限制.当遇见(Maximum request lengt ...

  5. jquery 中上传的图片file文件,如果在html img元素中通过src展示 ,可以img的图片src属性直接去等于file文件吗,如果不可以的话,那么src怎么去展示file文件呢

    bot回答: Answer: 不可以.文件不能直接设置为 img 元素的 src 属性值.要展示 file 文件,需要在 img 属性中使用 JavaScript 来实现,可以参考以下代码: < ...

  6. Android 加载大图片到内存

    本文演示android中图片加载到内存 首先设计界面: 代码如下: <LinearLayout xmlns:android="http://schemas.android.com/ap ...

  7. ionic build Android错误记录未解决

    1.try itcordova -v cordova create testing cd testing cordova plugin add cordova-plugin-sim cordova p ...

  8. 【经验记录】Android上传文件到服务器

    Android中实现上传文件,其实是很简单的,和在java里面是一样的,基本上都是熟悉操作输出流和输入流!还有一个特别重要的就是需要配置content-type的一些参数!如果这些都弄好了,上传就很简 ...

  9. ionic build Android错误记录 error in opening zip file

    0.写在前头 运行 :cordova requirements Requirements check results for android: Java JDK: installed 1.8.0 An ...

  10. Android群英传笔记——第九章:Android系统信息和安全机制

    Android群英传笔记--第九章:Android系统信息和安全机制 本书也正式的进入尾声了,在android的世界了,不同的软件,硬件信息就像一个国家的经济水平,军事水平,不同的配置参数,代表着一个 ...

随机推荐

  1. Understanding ANTLR Grammar Files

    Are you confused by all the different sections of an Antlr grammar file, wondering what each one doe ...

  2. Java Study For Six Day( 面向对象二)

    static(静态)关键字 用于修饰成员(成员变量和成员函数) 被修饰后的成员具备以下的特点 随着类的加载而加载 优先于对象存在 被所有的对象共享 可以被类名直接调用 静态注意事项 静态方法只能访问静 ...

  3. 编程辅助工具之Kite

    python作为一门门槛很低但又功能强大的编程语言,现在已经得到了非常广泛的使用,但是它的常用库非常多,而且往往更新后许多方法都有所变化,因此想要记住其大部分函数的用法对于大部分人来说比较困难,因而会 ...

  4. 工具篇-FinalShell

    转载:https://www.toutiao.com/i6694563184428188171?wid=1625538368131 FinalShell是一款免费的国产的集SSH工具.服务器管理.远程 ...

  5. TortoiseGit之私钥配置

    1.使用git命令生成公钥和私钥 ssh-keygen -t rsa -C "git邮箱账号" 三次回车,即可在~/.ssh/ 生成密钥对 id_rsa id_rsa.public ...

  6. SSD:清华出品,可切换密集稀疏的大模型预训练加速方案 | ICML'24

    来源:晓飞的算法工程笔记 公众号,转载请注明出处 论文: Exploring the Benefit of Activation Sparsity in Pre-training 论文地址:https ...

  7. 一步步教你学会如何区域录制屏幕转换成gif图

    现在各种表情包都是gif图,包括很多可能比较短暂的操作步骤,录制gif图也要远比录制成视频要来的方便很多. 1. GIF文件通常比视频文件小,这使得它们在网络传输中更加高效,尤其是在带宽有限的情况下. ...

  8. Javascript 异步处理

    1.传统异步处理 ES6之前使用回调进行处理,示例代码: //创建一个异步返回 双倍数值 的函数 function asyncDouble(num,cb){ // 创建标识,表示该异步处理是否完成 v ...

  9. sql 依据时间间隔分组,获取第一条数据

    时序数据的数据量比较大,抛去异常点外,变化相对比较有线性规律,业务上需要对结果进行抽取显示. 原始数据时序标签(部分示例) 根据时间字段,计算时间字段和指定时间的时间戳差值,然后除以固定间隔(示例中间 ...

  10. webpack-dev-server配置https

    前情 最近在做一个浏览器通知的交互需求,但是查阅官方文挡,浏览器通知需要在https环境下才能工作,于是就研究怎么在开发环境下配置一个https服务器 STEP1 安装Chocolatey Choco ...