需求
項目是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 "";
}