移动手机中实现端文件上传的例子

 更新时间:2016年9月20日 19:58  点击:1644
移动手机中实现端文件上传是现在WEB开发中也需要考虑到的一个问题,在这里我们来介绍使用XMLHttpRequest 结合Nodejs实现移动端文件上传了,下面我们一起来看看相关例子吧,希望文章能给各位带来帮助哦。

input[type="file"] 可以选择手机里的文件,还可以调用拍照功能(某些浏览器不行),Form 表单如下:

 代码如下 复制代码
<form id="upload-form" action="/upload" enctype="multipart/form-data" method="post">
  <input id="selece-files" type="file" name="fileToUpload" />
  <input id="do-upload" type="submit" value="上传" />
</form>

这里做单文件上传,多文件上传可以给 input[type="file"] 加个 multiple 属性便可。当触发 submit 事件提交:

 代码如下 复制代码


var Upload = (function(win, upload) {

  upload.submit = function() {
    var self = this,
      form = document.getElementById('form'),
      formdata = new FormData(form),
      xhr = new XMLHttpRequest();

    // xhr.upload 在 iOS Safari、 大部分 Android 4.0+ 的自带浏览器、Chrome 都支持
    xhr.upload.addEventListener("progress", self.onProgress, false);
    xhr.addEventListener("load", self.onSuccess, false);
    xhr.addEventListener("error", self.onError, false);
    xhr.addEventListener("abort", self.onCancel, false);

    xhr.open('post', form.action, false);
    xhr.send(formdata);
  }

  // 可以在 onProgress 的时候处理进度条
  upload.onProgress = function(e) {
    if (e.lengthComputable) {
      var progress = Math.round(e.loaded * 100 / e.total) + '%';
      console.log('on progress: ', progress);
    }
  }

  upload.onError = function() {}
  upload.onCancel = function() {}

  // 上传完成
  upload.onSuccess = function() {}

  return upload;

})(window, window.Upload || {});
FormData,这是另一种针对 XHR2 设计的新数据类型。使用 FormData 能够很方便地实时以 JavaScript 创建 HTML <form>。

Server 端用了 formidable 这个中间件:npm install formidable。
当然不用 formidable 也能处理文件上传。

 代码如下 复制代码

var fs = require('fs'),
  formidable = require('formidable');

app.post('/upload', function(req, res) {
  var form = new formidable.IncomingForm(),
    data;

  // formidable 属性设置可以参考 github 上说明
  form.uploadDir = './uploads';
  form.encoding = 'utf-8';
  form.keepExtensions = true;
  form.maxFieldsSize = 1024 * 1024 * 50; // 50MB

  form.parse(req, function(err, fields, files) {
    console.log('on parse');
    res.writeHead(200, {'content-type': 'text/plain'});
    data = files.fileToUpload;
    res.end(JSON.stringify(data));
  });

  // 我们可以在文件上传完成后移到放置文件的目标目录
  form.on('end', function() {
    fs.renameSync(data.path, './uploads/'+ data.name);
  });
});

下面一起来看一个关于wpf使用WPFMediaKit调用平板(surface2)摄像头拍照,希望例子能给各位同学带来帮助哦。

wpf中怎么调用surface(或者其他平板)的摄像头进行拍照那?今天分享一下使用WPFMediaKit调用平板(surface2)摄像头拍照。

wpf使用WPFMediaKit调用平板(surface2)摄像头拍照

下载最新的代码,加入到项目中。

 

wpf使用WPFMediaKit调用平板(surface2)摄像头拍照


2、test项目引用WPFMediaKit

xaml代码:

 代码如下 复制代码
<Window x:Class="test.WPFMediaKitWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 xmlns:wpfmedia="clr-namespace:WPFMediaKit.DirectShow.Controls;assembly=WPFMediaKit"
Title="WPFMediaKitWindow" Loaded="Window_Loaded"WindowState="Maximized">
<Grid>
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<ComboBox Name="cb" SelectionChanged="cb_SelectionChanged" Width="100" />
<Button Content="打开摄像头" x:Name="btnOpen" Click="btnOpen_Click"Width="100"/>
<Button Content="拍照" x:Name="btnCapture" Click="btnCapture_Click"Width="100" />
<Button Content="保存" x:Name="btnSave" Click="btnSave_Click" Width="100" />
</StackPanel>
<wpfmedia:VideoCaptureElement Name="vce" />
 
</StackPanel>
</Grid>
</Window>

后台代码:

获取摄像头:

 代码如下 复制代码
private void cameraOpen()
{
cb.ItemsSource = MultimediaUtil.VideoInputNames;
if (MultimediaUtil.VideoInputNames.Length > 1)
{
cb.SelectedIndex = 1;
}
else
{
cb.SelectedIndex = 0;
}
}

拍照保存到硬盘:win8注意有文件夹的权限问题

 代码如下 复制代码


private void TakePhoto()
{
RenderTargetBitmap bmp = new RenderTargetBitmap(
(int)vce.ActualWidth, (int)vce.ActualHeight,
96, 96, PixelFormats.Default);
//vce.Stretch = Stretch.Fill;
vce.Measure(vce.RenderSize);
vce.Arrange(new Rect(vce.RenderSize));
bmp.Render(vce);
BitmapEncoder encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bmp));
using (MemoryStream ms = new MemoryStream())
{
encoder.Save(ms);
CaptureData = ms.ToArray();
File.WriteAllBytes(@"C:aaaa" + DateTime.Now.ToString("yyyy-mm-dd-hh-mm-sss")+".png", CaptureData);
}
vce.Play();
//capCreateCaptureWindowA()
return;
}

经过这么久在android客户端和服务器端的开发,感觉还是积累了不少东西想要和大家分享一下,但是好想单独拎一个点出来又不太值得,所以就汇集到一起写成系列吧。

一. 关于用户数据存储

首先在注册的协议里,定义如下公共传输字段:

version: 这个其实是xml中配置的versionCode。versionName个人认为没有什么必要,所以就不传了。

channel:  用户渠道,这个和xml中的UMENG_CHANNEL 是共用的,因为一直在使用umeng,所以这样定义反而清楚一些。

device_id: 设备ID

os: 操作系统类型,这里默认传入android

os_version: 操作系统版本

对于小数据量,用户数据存储在mysql中是相对较好的选择,这里直接以django的model为例:

 代码如下 复制代码
from django.db import models
class User(models.Model):
    device_id = models.CharField(max_length=255, null=True, blank=True)
    version = models.IntegerField()
    channel = models.CharField(max_length=64, null=True, blank=True)
    os = models.CharField(max_length=64, null=True, blank=True)
    os_version = models.CharField(max_length, null=True, blank=True)
    create_time = models.DateTimeField(default=get_cur_time)
    login_time = models.DateTimeField(default=get_cur_time)


如果需要用到如facebook之类的联合登录,对于小规模的服务,我个人倾向于不破坏User的定义,因为毕竟这种联合登录什么时候会加入很难预知:

 代码如下 复制代码
class FBUser(models.Model):
    # facebook 用户ID
    userid = models.CharField(max_length=32, unique=True)
    # User.id,这里不用外键,是为了以后拆分表或者换数据存储留下后路
    native_id = models.IntegerField(default=0)
 
    def __unicode__(self):
        return '%s-&gt;%s' % (self.userid, self.native_id)


其他的业务相关的字段定义就由业务自己决定了。

我不是很建议在未来可能数据量很大的表里使用 外键,因为很可能以后要设计到分库分表、或者迁移数据到redis、mongodb之类的,这在我之前的博文里面就有提到过,大家有兴趣可以看一下。

 

二. 关于通信协议的选择

其实这块还真的有不少东西可以说的。

HTTP

最简单的肯定是用http协议,但是http协议在手机应用上其实只能满足传统一收一发的需求,即使是使用long poll之类技术,经过我测试,当在3G网络下时,运营商经常会强制返回http请求为502错误。

WebSocket

当然,如果对http还是心有所属,可以使用 websocket,经过测试 websocket还是比较好用的,cocos2d-x 有专门提供websocket的封装,android下也有专门的websocket的库: AndroidAsync

python也提供了很多websocket的server和client。比如server端有 gevent-websocket、以及在其基础上开发的flask plugin: flask-sockets。当然django也是可以直接使用gevent-websocket的,django还有一个不基于gevent的版本:django-websocket。client端有 websocket-client。

基于gevent的server之前测试过,可以正常的收到断掉链接的消息,逻辑处理也都比较正常。最终要的一点是,他可以和现有http服务器无缝结合,不需要做跨进程在两个server间通讯。

SocketIO

这个我也测试过,但是实在不建议大家在项目中使用,他做了太多的兼容的事情了,而我们客户端又不是浏览器,根本不需要考虑那么多事情,只要用一种协议就可以了。

还有一点就是,我试了下python的socketio server似乎有点问题,在客户端主动close链接时,服务器端并没有收到事件,而只有客户端发送disconnect命令才会触发服务器端的相关事件。这个事情在网上查了一下,貌似是官方故意做的处理,防止浏览器在刷新时触发一些奇怪的事情,但是这样处理对于我是无法忍受的。

不过还是把相关的链接发给大家,大家可以试一下。android客户端:还是  AndroidAsync。 python server端:Flask-SocketIO,django-socketio,python client端:socketIO-client。

原生socket+自定义协议

这种方式灵活度肯定是最高的,但是相应的开发难度肯定也会增大。协议可以使用json或者google 的 protobuf。这个可能一两句话还说不清楚,下一篇我们专门花篇幅聊一下。

下面本文章来给各位同学介绍一个关于Android中POST请求中的UTF-8编码问题解决办法,如果你碰到不防进入参考。

今天遇到这样一个bug:客户端POST到服务器的一段数据导致服务器端发生未知异常。服务器端确认是编码转换错误。于是截取网络数据包进行分析,发现客户端POST的json数据中包含下面一段(hex形式):

... 61 64 20 b7 20 52 69 63 ...

问题就出在这个b7上。查阅Unicode代码表后发现,U+00b7是MIDDLE DOT,它的UTF-8表现形式应该是c2 b7,但为何客户端发送的数据中它变成了b7?

由于系统使用了ormlite、gson和async-http几个库,于是逐一排查。最后发现原来是向服务器发送数据时没有指定文字编码,导致async-http(实际是apache common http client)将数据以ISO-8559-1格式发送,U+00b7被编码成b7,然后服务器试图使用UTF-8解码时发生错误。

出错的代码片段如下:

 代码如下 复制代码

Gson gson = new Gson();
String json = gson.toJson(data);
StringEntity entity = new StringEntity(json);
httpClient.post(context, url, entity, "application/json", new TextHttpResponseHandler() ... );

第三行new StringEntity(json)时没有指定编码导致错误。改正后如下:

 代码如下 复制代码

Gson gson = new Gson();
String json = gson.toJson(data);
StringEntity entity = new StringEntity(json, "utf-8");
httpClient.post(context, url, entity, "application/json;charset=utf-8", new TextHttpResponseHandler() ... );

 

在android开发过程中,APP需要用到摄像头录制视频音效、播放视频的功能,并且通过第三方线程调用Handler动态的addview和removeview添加和删除播放视频的组件——MediaPlayer。

一、产生异常原因

每次在点播放按钮的时候,打开MediaPlayer的SurfaceView进行播放,再次点击则删除波翻组件,停止播放,这个过程中会遇到The surface has been released 错误,这个的原因是因为:在播放this.mediaPlayer.start()之前SurfaceView没有来的及调用onCreate()或者onChange()方法,导致holder没有成功加载,所以在start播放的时候抛出播放异常。

二、解决办法

很简单的办法就是:
1.设置一个boolean标志位isSurfaveCreated,在执行onCreate()或者onChange()之后,将isSurfaveCreated=true。
2.在停止播放之后isSurfaveCreated=false。
3.在MediaPlayer.setDisplay()之前使用while循环以及Thread.sleep(10)来循环检测isSurfaveCreated,只有isSurfaveCreated为true的时候,才继续执行,具体代码为:

 代码如下 复制代码
while (! this.isSurfaveCreated) {
    try {
        Thread.sleep(10);
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

当然,这个办法自己感觉是一个非主流的办法,但是确实可以很好的避免这个问题,除此之外,大家自己考虑代码的安全稳定性等等因素,Enjoy~

[!--infotagslink--]

相关文章

  • php读取zip文件(删除文件,提取文件,增加文件)实例

    下面小编来给大家演示几个php操作zip文件的实例,我们可以读取zip包中指定文件与删除zip包中指定文件,下面来给大这介绍一下。 从zip压缩文件中提取文件 代...2016-11-25
  • 安卓手机app添加支付宝支付开发教程

    支付宝支付在国内算是大家了,我们到处都可以使用支付宝了,下文整理介绍的是在安卓app应用中使用支付宝进行支付的开发例子。 之前讲了一篇博客关与支付宝集成获取...2016-09-20
  • Jupyter Notebook读取csv文件出现的问题及解决

    这篇文章主要介绍了JupyterNotebook读取csv文件出现的问题及解决,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2023-01-06
  • PHP+Ajax手机发红包的程序例子

    PHP+Ajax有许多的功能都会用到它小编今天就有使用PHP+Ajax实现的一个微信登录功能了,下面我们来看一个PHP+Ajax手机发红包的程序例子,具体如下所示。 PHP发红包基本...2016-11-25
  • 华为手机怎么恢复已卸载的应用?华为手机恢复应用教程

    华为手机怎么恢复已卸载的应用?有时候我们在使用华为手机的时候,想知道卸载的应用怎么恢复,这篇文章主要介绍了华为手机恢复应用教程,需要的朋友可以参考下...2020-06-29
  • Photoshop打开PSD文件空白怎么解决

    有时我们接受或下载到的PSD文件打开是空白的,那么我们要如何来解决这个 问题了,下面一聚教程小伙伴就为各位介绍Photoshop打开PSD文件空白解决办法。 1、如我们打开...2016-09-14
  • 破解安卓手机上的九宫格锁方法步骤

    很多用安卓智能手机的朋友是用九宫格锁屏,网上也有暴力删除手机图形锁的方法,不过我们可以用程序来破解。本文只提供技术学习,不能干坏事 安卓手机的图形锁(九宫格)...2016-09-20
  • 解决python 使用openpyxl读写大文件的坑

    这篇文章主要介绍了解决python 使用openpyxl读写大文件的坑,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-03-13
  • C#实现HTTP下载文件的方法

    这篇文章主要介绍了C#实现HTTP下载文件的方法,包括了HTTP通信的创建、本地文件的写入等,非常具有实用价值,需要的朋友可以参考下...2020-06-25
  • SpringBoot实现excel文件生成和下载

    这篇文章主要为大家详细介绍了SpringBoot实现excel文件生成和下载,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-02-09
  • C#操作本地文件及保存文件到数据库的基本方法总结

    C#使用System.IO中的文件操作方法在Windows系统中处理本地文件相当顺手,这里我们还总结了在Oracle中保存文件的方法,嗯,接下来就来看看整理的C#操作本地文件及保存文件到数据库的基本方法总结...2020-06-25
  • 华为手机怎么开启双时钟? 华为添加双时钟的技巧

    华为手机怎么开启双时钟?华为手机是可以设置双时钟的,如果来回在两个有时差的地方工作,是可以设置双时钟显示,下面我们就来看看华为添加双时钟的技巧,需要的朋友可以参考下...2020-12-08
  • php无刷新利用iframe实现页面无刷新上传文件(1/2)

    利用form表单的target属性和iframe 一、上传文件的一个php教程方法。 该方法接受一个$file参数,该参数为从客户端获取的$_files变量,返回重新命名后的文件名,如果上传失...2016-11-25
  • Php文件上传类class.upload.php用法示例

    本文章来人大家介绍一个php文件上传类的使用方法,期望此实例对各位php入门者会有不小帮助哦。 简介 Class.upload.php是用于管理上传文件的php文件上传类, 它可以帮...2016-11-25
  • 安卓手机wifi打不开修复教程,安卓手机wifi打不开解决方法

    手机wifi打不开?让小编来告诉你如何解决。还不知道的朋友快来看看。 手机wifi是现在生活中最常用的手机功能,但是遇到手机wifi打不开的情况该怎么办呢?如果手机wifi...2016-12-21
  • php批量替换内容或指定目录下所有文件内容

    要替换字符串中的内容我们只要利用php相关函数,如strstr,str_replace,正则表达式了,那么我们要替换目录所有文件的内容就需要先遍历目录再打开文件再利用上面讲的函数替...2016-11-25
  • PHP文件上传一些小收获

    又码了一个周末的代码,这次在做一些关于文件上传的东西。(PHP UPLOAD)小有收获项目是一个BT种子列表,用户有权限上传自己的种子,然后配合BT TRACK服务器把种子的信息写出来...2016-11-25
  • jQuery实现简单的文件上传进度条效果

    本文实例讲述了jQuery实现文件上传进度条效果的代码。分享给大家供大家参考。具体如下: 运行效果截图如下:具体代码如下:<!DOCTYPE html><html><head><meta charset="utf-8"><title>upload</title><link rel="stylesheet...2015-11-24
  • AI源文件转photoshop图像变模糊问题解决教程

    今天小编在这里就来给photoshop的这一款软件的使用者们来说下AI源文件转photoshop图像变模糊问题的解决教程,各位想知道具体解决方法的使用者们,那么下面就快来跟着小编...2016-09-14
  • Zend studio文件注释模板设置方法

    步骤:Window -> PHP -> Editor -> Templates,这里可以设置(增、删、改、导入等)管理你的模板。新建文件注释、函数注释、代码块等模板的实例新建模板,分别输入Name、Description、Patterna)文件注释Name: 3cfileDescriptio...2013-10-04