[记录点滴]在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 参考
[记录点滴]在Ionic和Android中上传Blob图片的更多相关文章
- .net项目中上传大图片失败
.net项目中有时用户提出要上传大图片,一张图片有可能十几兆,本来用的第三方的上传控件,有限制图片上传大小的设置,以前设置的是2M.按照用户的要求,以为直接将限制图片上传大小的设置改下就可以了,但是当 ...
- .net项目中上传的图片或者文件太大 无法上传
最近做项目的时候 用户提出要上传大图片 一张图片有可能十几兆 本来用的第三方的上传控件 有限制图片上传大小的设置 以前设置的是2M 按照用户的要求 以为直接将限制图片上传大小的设置改下就可 ...
- TP中上传文件图片的实现
GoodsController.class.php控制器页面<?php namespace Admin\Controller; use Think\Controller; class Goods ...
- 【应用服务 App Service】App Service中上传文件/图片(> 2M)后就出现500错误(Maximum request length exceeded).
问题描述 在使用App Service (Windows)做文件/图片上传时候,时常遇见上传大文件时候出现错误,这是因为IIS对文件的大小由默认限制.当遇见(Maximum request lengt ...
- jquery 中上传的图片file文件,如果在html img元素中通过src展示 ,可以img的图片src属性直接去等于file文件吗,如果不可以的话,那么src怎么去展示file文件呢
bot回答: Answer: 不可以.文件不能直接设置为 img 元素的 src 属性值.要展示 file 文件,需要在 img 属性中使用 JavaScript 来实现,可以参考以下代码: < ...
- Android 加载大图片到内存
本文演示android中图片加载到内存 首先设计界面: 代码如下: <LinearLayout xmlns:android="http://schemas.android.com/ap ...
- ionic build Android错误记录未解决
1.try itcordova -v cordova create testing cd testing cordova plugin add cordova-plugin-sim cordova p ...
- 【经验记录】Android上传文件到服务器
Android中实现上传文件,其实是很简单的,和在java里面是一样的,基本上都是熟悉操作输出流和输入流!还有一个特别重要的就是需要配置content-type的一些参数!如果这些都弄好了,上传就很简 ...
- ionic build Android错误记录 error in opening zip file
0.写在前头 运行 :cordova requirements Requirements check results for android: Java JDK: installed 1.8.0 An ...
- Android群英传笔记——第九章:Android系统信息和安全机制
Android群英传笔记--第九章:Android系统信息和安全机制 本书也正式的进入尾声了,在android的世界了,不同的软件,硬件信息就像一个国家的经济水平,军事水平,不同的配置参数,代表着一个 ...
随机推荐
- 设计模式【3.1】-- 浅谈代理模式之静态、动态、cglib代理
代理模式:为其他对象提供一种代理以控制对这个对象的访问,在某种情况下,一个对象不适合或者不能够直接引用另一个对象,而代理对象可以在客户类和目标对象之间起到中介的作用. 可以这么理解:使用代理对象,是为 ...
- .NET Core 异步(Async)底层原理浅谈
简介 多线程与异步是两个完全不同的概念,常常有人混淆. 异步 异步适用于"IO密集型"的场景,它可以避免因为线程等待IO形成的线程饥饿,从而造成程序吞吐量的降低. 其本质是:让线程 ...
- 终于解决了.net在线客服系统总是被360误报的问题(对软件进行数字签名)
升讯威在线客服与营销系统是基于 .net core / WPF 开发的一款在线客服软件,宗旨是: 开放.开源.共享.努力打造 .net 社区的一款优秀开源产品. 背景 我在业余时间开发的这个客服系统, ...
- K8S钩子、探针以及控制器完整版
一. 生命周期钩子 Kubernetes 中的 生命周期钩子(Lifecycle Hooks) 是在容器生命周期的特定阶段执行操作的机制.通过钩子,可以在容器启动后(PostStart)或停止前(Pr ...
- #oscp#渗透测试 kioptix level 3靶机getshell及提权教程
声明! 文章所提到的网站以及内容,只做学习交流,其他均与本人以及泷羽sec团队无关,切勿触碰法律底线,否则后果自负!!!! 一.靶机搭建 点击扫描虚拟机 选择靶机使在文件夹即可 二.信息收集 前言 信 ...
- dockerfile实现tomcat以及java的war包自动部署
1. 下载jdk和tomcat wget https://dlcdn.apache.org/tomcat/tomcat-8/v8.5.93/bin/apache-tomcat-8.5.93.tar.g ...
- cookie session token 发展史(便于理解jwt)
目录 一.cookie session token 发展史(彻底理解cookie,session,token,便于理解jwt) 1.Cookie,Session,Token发展史 2.Cookie,S ...
- Qt/C++自定义界面大全/20套精美皮肤/26套精美UI界面/一键换肤/自定义颜色/各种导航界面
一.前言 这个系列对应自定义控件大全,一个专注于控件的编写,一个专注于UI界面的编写,程序员有两大软肋,一个是忌讳别人说自己的程序很烂很多bug,一个就是不擅长UI,基本上配色就直接rgb,对于第一点 ...
- Qt开源作品39-日志输出增强版V2022
一.前言 之前已经开源过基础版本,近期根据客户需求和自己的项目需求,提炼出通用需求部分,对整个日志重定向输出类重新规划和重写代码. 用Qt这个一站式超大型GUI超市做开发已经十二年了,陆陆续续开发过至 ...
- 安装Visual Studio2015后找不到C++项目模板解决办法
安装Visual Studio2015后找不到C++项目模板解决办法: 方法1:您可以通过修改Visual Studio来完成此操作,并且可以使用以下步骤完成此操作:1.转到"添加或删除程序 ...