Vue项目中实现数据上传(文本信息、图片、视频以及拍照视频录像)
- 需求
- 功能步骤
- 代码实现
需求
项目是vue开发的webapp,使用cordova打包生成。项目可支持文本数据上传、app选择本地图库、本地视频上传、以及手机拍照录像上传。
功能步骤
1、项目使用vant中van-uploader组件实现访问本地图库。
2、项目中涉及文本信息上传、图片上传、视频上传。
3、项目中使用cordova插件实现调起摄像机进行拍照、录像。
4、项目中使用ffmpeg在c#创建的后台中进行视频转码,对所有视频统一做格式处理。
项目中dom操作以及css部分不做阐述。
- 安装cordova插件
在cordova官网插件中搜索cordova-plugin-camera、cordova-plugin-android-permissions、cordova-plugin-file、cordova-plugin-file-transfer、cordova-plugin-media-capture插件
进入命令行工具安装执行
cd test //进入cordova工程
cordova plugin add cordova-plugin-camera //相机
cordova plugin add cordova-plugin-android-permissions // 检测权限是否打开安装插件
dordova plugin add cordova-plugin-file //采用cordova录像的视频通过专用方式文件上传
cordova plugin add cordova-plugin-file-transfer
cordova plugin add cordova-plugin-media-capture//录像
代码实现
- 文本信息及本地视频图片上传
###前端获取本地file
handleBeforeUpload(file, fileobj) {
if (file.name.substr(file.name.lastIndexOf('.'), 4).toLowerCase() == ".mp4" ) {
let reader = new FileReader()
reader.readAsDataURL(file)
reader.onloadend = function (e) {
file.url = e.target.result;//给视频file对象增加url属性
this.uploadList.push(file) //存入视频数组
this.uploadListVideo.push(file)
}
}
else if (file.name.substr(file.name.lastIndexOf('.'), 4).toLowerCase() == ".jpg" {
let reader = new FileReader()
reader.readAsDataURL(file)
reader.onloadend = function (e) {
file.url = reader.result //给file增加url属性
this.TraveluploadList.push(file)//存入图片数组
this.TraveluploadListPicture.push(file)
}
}
}
##前端上传文本本地图片视频
var Jsondata = "{'functionname': 'uploaderAnimalProduct','name':'" + this.Animalname + "'}"//获取文本信息
var formData = new FormData()
for (let i = 0; i < this.uploadListPicture.length; i++) {
formData.append('file', this.uploadListPicture[i], this.uploadListPicture[i].name)//将图片添加到formdata中
}
for (let i = 0; i < this.uploadListVideo.length; i++) {
formData.append('file', this.uploadListVideo[i], this.uploadListVideo[i].name)//将视频添加到formdata中
}
formData.append('data', Jsondata);
var jsontext = encodeURIComponent('{"functionname":"uploader"}');
this.$http.post(this.common.WebServiceAddress + jsontext + "").then(response => {
let server = response.data.d;//返回后端地址
this.$http.post(server + '/FarmInfo_picture', formData).then(res => {
console.log("上传成功")
})
})
### 后端接收
string resultjson = null;
//获取服务器上图片当前文件夹并对其操作,对文件的读取
HttpFileCollection File = HttpContext.Current.Request.Files;
//接收webuploader带参数formdata表单的方法
NameValueCollection from = HttpContext.Current.Request.Form;
JObject jsonLogic = new JObject();
jsonLogic = (JObject)JsonConvert.DeserializeObject(from["data"].ToString());
string str = jsonLogic["functionname"].ToString();
string strJson = from["data"].ToString();
public string UploaderProductPicture(string strJson, HttpFileCollection file)
{
string jsontext = "";
JObject jsonDB = new JObject();
jsonDB = (JObject)JsonConvert.DeserializeObject(strJson);
string name = jsonDB["name"].ToString();
if (file.Count > 0)
{
for (int i = 0; i < file.Count; i++)
{
HttpPostedFile fileSave = file[i];
string filename = fileSave.FileName;
if (!Directory.Exists(commonV.IP + commonV.savePath + keyid + "/"))
{
Directory.CreateDirectory(commonV.IP + commonV.savePath + keyid + "/");
}
fileSave.SaveAs(commonV.IP + commonV.savePath + keyid + "/" + newguid + filename);
}
}
}
- 利用cordova插件拍照
###利用cordova插件调起相机
navigator.camera.getPicture(this.onSuccess, this.onFail, {
quality: 50,
destinationType: Camera.DestinationType.DATA_URL, // js应用慢到窒息
encodingType: Camera.EncodingType.JPEG,
// encodingType: Camera.EncodingType.Mp4,
sourceType: Camera.PictureSourceType.CAMERA,
saveToPhotoAlbum: true,
// sourceType:Camera.PictureSourceType.PHOTOLIBRARY
});
onSuccess(file){
let _this = this
let file = this.dataURLtoFile('data:image/jpeg;base64,' + imageData, 'test.jpeg')
let readerBlob = new FileReader()
readerBlob.readAsDataURL(file)
readerBlob.onloadend = function (e) {
file.url = e.target.result
_this.uploadList.push(transFile)
_this.uploadListPicture.push(transFile)
}
}
dataURLtoFile(dataurl, filename){//将url转为blob对象
var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
var blob = new Blob([u8arr], {type: mime})
blob.lastModifiedDate = new Date()
blob.name = filename
return blob;
},
图片上传类似,不做赘述
- 利用cordova插件进行录像
###利用cordova插件录像
let permissions = cordova.plugins.permissions;### 利用cordova插件检查是否打开应用存储等权限
permissions.hasPermission(permissions.WRITE_EXTERNAL_STORAGE, this.checkPermissionCallback, null)//检测是否具有相应权限
checkPermissionCallback(status){
var options = {
imit: 1,
duration: 15
};
var permissions = cordova.plugins.permissions;
if (!status.hasPermission) {
permissions.requestPermission(permissions.WRITE_EXTERNAL_STORAGE, this.requestPermissionCallback, this.errorCallback);//请求相应权限
}
else {
navigator.device.capture.captureVideo(this.uploadVideo, this.onErrorMedia, options);//执行录像功能
}
},
####录像部分的视频前端上传
uploadVideo(files) {
var fileURL = files[0].url
var options = new FileUploadOptions()
options.fileKey = 'file';
options.fileName = fileURL.substr(fileURL.lastIndexOf('/') + 1);
options.mimeType = "text/plain";
var params = {
data: {
functionname: 'videoTranscode', //传入后端进行转码操作
keyid: _this.keyid
}
};
options.params = params;
var ftt = new FileTransfer();//使用插件类上传方式。
var jsontext = encodeURIComponent('{"functionname":"uploader"}');
this.$http.post(_this.common.WebServiceAddress + jsontext + "").then(response => {
let server = response.data.d;
ftt.upload(fileURL, encodeURI(server), _this.transcodewin,_this.fail, options);
})
}
}
}
- 利用ffmpeg进行后端转码
public string VideoTranscode(string strJson, HttpFileCollection file)
{
static string FFmpegPath = commonV.ffmpegPath;
string para = string.Format("-i {0} -vcodec h264 -s 480*720 -f mp4 {1}", commonV.IP + commonV.VideoPathBefore + "/" + keyid + path_save, commonV.IP + commonV.VideoPathBefore + "/" + keyid + path_save1);
Process p = new Process();
try
{
p.StartInfo.FileName = FFmpegPath;
p.StartInfo.Arguments = para;
//是否使用操作系统shell启动
// p.StartInfo.UseShellExecute = false;
//不显示程序窗口
p.StartInfo.CreateNoWindow = true;
DateTime beginTime = DateTime.Now;
p.EnableRaisingEvents = true;
p.Start();
// Console.WriteLine("\n开始转码...\n");
p.WaitForExit();
}
catch (Exception ex)
{
// Console.WriteLine("\n错误!!" + ex.ToString());
///p.kill();杀死该进程
//感觉应该在这儿加代码测试如果没有转码完成,删除未完成对应的转码视频
}
finally
{
}
}
- 利用ffmpeg进行提取第一帧图片
string PicName = commonV.IP + commonV.travelVideoPathBefore + "/" + keyid + "/" + picturename + ".jpg";//视频图片的名字,绝对路径
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo(FFmpegPath);
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
startInfo.Arguments = " -i " + VideoName //视频路径
+ " -r 1" //提取图片的频率
+ " -y -f image2 -ss " + CutTimeFrame //设置开始获取帧的视频时间
+ " -t 00:00:01 -s " + WidthAndHeight //设置图片的分辨率
+ @" " + commonV.IP + commonV.travelVideoPathBefore + "/" + keyid + "/" + picturename + ".jpg"; //输出的图片文件名,路径前必须有空格
try
{
System.Diagnostics.Process.Start(startInfo);
Thread.Sleep(5000);//线程挂起,等待ffmpeg截图完毕
}
catch (Exception)
{
return "";
}