-
-
Save chmiiller/0b51e5a19f1a9cf63af85d81be5dd0e2 to your computer and use it in GitHub Desktop.
Upload large video from Axway Titanium mobile application (iOS / Android) and save the video with PHP script
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Download and install widget loader : https://github.com/FokkeZB/nl.fokkezb.loading | |
Alloy.Globals.loading = Alloy.createWidget("nl.fokkezb.loading"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"global": {}, | |
"env:development": {}, | |
"env:test": {}, | |
"env:production": {}, | |
"os:android": {}, | |
"os:ios": {}, | |
"os:windows": {}, | |
"dependencies": { | |
"nl.fokkezb.loading": "*" | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8"?> | |
<ti:app | |
xmlns:ti="http://ti.appcelerator.org"> | |
<id>fr.squirrel.testVideo</id> | |
<name>testVideo</name> | |
<version>1.0</version> | |
<publisher>not specified</publisher> | |
<url>unspecified</url> | |
<description/> | |
<copyright>not specified</copyright> | |
<icon>appicon.png</icon> | |
<fullscreen>false</fullscreen> | |
<navbar-hidden>false</navbar-hidden> | |
<analytics>true</analytics> | |
<!--<guid></guid>--> | |
<property name="ti.ui.defaultunit" type="string">dp</property> | |
<property name="run-on-main-thread" type="bool">true</property> | |
<ios> | |
<enable-launch-screen-storyboard>true</enable-launch-screen-storyboard> | |
<use-app-thinning>true</use-app-thinning> | |
<plist> | |
<dict> | |
<key>NSMicrophoneUsageDescription</key> | |
<string>Autoriser à utiliser votre micro ?</string> | |
<key>NSPhotoLibraryUsageDescription</key> | |
<string>Autoriser à enregistrer des photos dans votre galerie ?</string> | |
<key>NSCameraUsageDescription</key> | |
<string>Autoriser à utiliser votre caméra ?</string> | |
<key>UISupportedInterfaceOrientations~iphone</key> | |
<array> | |
<string>UIInterfaceOrientationPortrait</string> | |
</array> | |
<key>UISupportedInterfaceOrientations~ipad</key> | |
<array> | |
<string>UIInterfaceOrientationPortrait</string> | |
<string>UIInterfaceOrientationPortraitUpsideDown</string> | |
<string>UIInterfaceOrientationLandscapeLeft</string> | |
<string>UIInterfaceOrientationLandscapeRight</string> | |
</array> | |
<key>UIRequiresPersistentWiFi</key> | |
<false/> | |
<key>UIPrerenderedIcon</key> | |
<false/> | |
<key>UIStatusBarHidden</key> | |
<false/> | |
<key>UIStatusBarStyle</key> | |
<string>UIStatusBarStyleDefault</string> | |
</dict> | |
</plist> | |
</ios> | |
<android | |
xmlns:android="http://schemas.android.com/apk/res/android"> | |
<manifest> | |
<uses-permission android:name="android.permission.CAMERA"/> | |
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> | |
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> | |
</manifest> | |
</android> | |
<modules> | |
<module platform="commonjs">ti.cloud</module> | |
</modules> | |
<deployment-targets> | |
<target device="android">true</target> | |
<target device="ipad">true</target> | |
<target device="iphone">true</target> | |
</deployment-targets> | |
<sdk-version>7.0.1.GA</sdk-version> | |
<plugins> | |
<plugin version="1.0">ti.alloy</plugin> | |
</plugins> | |
</ti:app> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$.index.open(); | |
var url = Ti.App.Properties.getString('url', 'http://'); | |
$.txt.value = url; | |
var userid = Ti.App.Properties.getString('userid', ''); | |
$.user.value = userid; | |
var videoPlayer = null; | |
function setNewVideo(videoplayer, url){ | |
if(videoPlayer) | |
$.videoPlayer.remove(videoPlayer); | |
videoPlayer = Ti.Media.createVideoPlayer({ | |
autoplay: true, | |
mediaControlStyle: Ti.Media.VIDEO_CONTROL_DEFAULT, | |
scalingMode: Ti.Media.VIDEO_SCALING_ASPECT_FIT, | |
}); | |
videoPlayer.url = url; | |
$.videoPlayer.add(videoPlayer); | |
videoPlayer.addEventListener('click',function(e){ | |
videoPlayer.play(); | |
}); | |
} | |
function takeVideo() { | |
var dialog = Ti.UI.createAlertDialog({ | |
message: "Prendre une vidéo", | |
buttonNames: ['Depuis la galerie', "Nouvelle vidéo", "Annuler"], | |
cancel: 2 | |
}); | |
dialog.show(); | |
dialog.addEventListener('click', function(e){ | |
if(e.index !== e.source.cancel){ | |
if(e.index === 0){ | |
Ti.Media.openPhotoGallery({ | |
mediaTypes: [Ti.Media.MEDIA_TYPE_VIDEO], | |
videoMaximumDuration: 90000, | |
success: function(ee){ | |
Alloy.Globals.mediaPath = OS_IOS ? Ti.Filesystem.getFile(ee.media.path) : Ti.Filesystem.getFile(ee.media.file.nativePath); | |
chunkedXHR(url,Alloy.Globals.mediaPath,onSuccess); | |
setNewVideo(videoPlayer,OS_IOS ? ee.media.path : ee.media.file.nativePath); | |
}, | |
error: function(ee){ | |
$.log.value = 'Erreur lors de l\'ouverture de la galerie : '+JSON.stringify(ee)+'...\n'+$.log.value; | |
} | |
}); | |
} | |
else{ | |
if(!Ti.Media.hasCameraPermissions()){ | |
Ti.Media.requestCameraPermissions(function(e){ | |
if(e.success){ | |
showCamera(); | |
}else{ | |
$.log.value = 'Erreur lors de la demande d\'autorisation : '+JSON.stringify(e)+'...\n'+$.log.value; | |
} | |
}); | |
} | |
else{ | |
showCamera(); | |
} | |
} | |
} | |
}); | |
} | |
function showCamera(){ | |
Ti.Media.showCamera({ | |
mediaTypes: [Ti.Media.MEDIA_TYPE_VIDEO], | |
videoMaximumDuration: 90000, | |
success: function(e){ | |
Alloy.Globals.mediaPath = OS_IOS ? Ti.Filesystem.getFile(e.media.path) : Ti.Filesystem.getFile(e.media.file.nativePath); | |
// videoPlayer.url = OS_IOS ? e.media.path : e.media.file.nativePath; | |
Alloy.Globals.loading.show(); | |
urlVideo = OS_IOS ? e.media.path : e.media.file.nativePath; | |
chunkedXHR(url,Alloy.Globals.mediaPath,onSuccess); | |
_.defer(function(){ | |
setNewVideo(videoPlayer,urlVideo); | |
}); | |
}, | |
error: function(e){ | |
$.log.value = 'Erreur lors de la prise de vidéo : '+JSON.stringify(e)+'...\n'+$.log.value; | |
} | |
}); | |
} | |
function chunkedXHR(url, file,callback){ | |
var url = $.txt.value; | |
var userid = $.user.value; | |
Ti.App.Properties.setString('url', url); | |
Ti.App.Properties.setString('userid', userid); | |
if(file){ | |
var chunk_size = OS_IOS ? 1048576 * 1 : 1048576 * 10; // 1M | |
var xhr = Ti.Network.createHTTPClient(); | |
xhr.setRequestHeader('Content-Type', 'application/json'); | |
xhr.setRequestHeader('userid', userid); | |
Alloy.Globals.loading.show('Envoi de la vidéo...',function(){ | |
xhr.abort(); | |
$.log.value = 'Annulation de l\'envoi...\n'+$.log.value; | |
}); | |
var size = file.size; | |
var chunks = Math.ceil(size/chunk_size); | |
var stream = file.open(Ti.Filesystem.MODE_READ); | |
var buffer = Ti.createBuffer({length: chunk_size}); | |
var chunk = 1; | |
var bytes = 0; | |
var name = file.name; //important! Pour concaténer les morceaux | |
xhr.onload = function(e) { | |
if (chunks == chunk) { | |
buffer.release(); | |
callback(e); | |
} else { | |
chunk++; | |
go(); | |
} | |
}; | |
xhr.onerror = onError; | |
var go = function() { | |
if (chunk == chunks) { | |
// last chunk | |
var length = size - chunk_size*(chunk-1); | |
buffer.setLength(length); | |
} | |
bytes = stream.read(buffer); | |
if (!bytes) return; | |
var data = {}; | |
data.data = buffer.toBlob(); | |
data.chunk = chunk; | |
data.chunks = chunks; | |
data.filename = name; | |
xhr.open('POST', url); | |
$.log.value = 'Envoi du morceau (NOM du fichier : '+name+') : N° '+chunk+'/'+chunks+' sur l\'url : '+url+' (userid : '+userid+') ...\n'+$.log.value; | |
xhr.send(data||{}); | |
}; | |
go(); | |
} | |
} | |
function onSuccess(response){ | |
Alloy.Globals.loading.hide(); | |
$.log.value = 'Envoi réussi ! '+JSON.stringify(response)+'...\n'+$.log.value; | |
} | |
function onError(e){ | |
Alloy.Globals.loading.hide(); | |
$.log.value = 'Erreur lors de l\'envoi : '+JSON.stringify(e)+'...\n'+$.log.value; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
//save the video into the upload directory | |
if(!isset($_POST['filename'])){ | |
echo 'Rien à faire ici'; | |
}else{ | |
$tmp = $_FILES['data']['tmp_name']; | |
$filenamebdd = $_POST['filename']; | |
$filename = './'.$_POST['filename']; | |
$chunk = isset($_POST['chunk']) ? $_POST['chunk'] : 0; | |
if($chunk > 1 ){ | |
$chunks = $_POST['chunks']; | |
exec("cat $tmp >> $filename"); | |
if ($chunks == $chunk) { | |
// stick the video with user id in database | |
//$res['success'] = $filenamebdd && $_POST['id_user'] ? true : false; | |
$res['success'] = true; | |
$res['url'] = $filenamebdd; | |
$res['chunk'] = $chunk; | |
$res['chunks'] = $chunks; | |
return json_encode($res); | |
} | |
} | |
else{ | |
move_uploaded_file($tmp, $filename); | |
$res['success'] = true; | |
$res['url'] = $filenamebdd; | |
$res['chunk'] = $chunk; | |
return json_encode($res); | |
} | |
} | |
?> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
".container": { | |
backgroundColor:"white" | |
} | |
"TextField": { | |
autocorrect: false, | |
autocapitalization: Ti.UI.TEXT_AUTOCAPITALIZATION_NONE, | |
value : 'http://', | |
hintText: "URL du serveur", | |
color: "black", | |
top : 20, | |
left : 20, | |
right : 20, | |
height : 40, | |
borderColor: "orange" | |
} | |
"ScrollView": { | |
width: Ti.UI.FILL, | |
height: Ti.UI.SIZE, | |
layout: "vertical" | |
} | |
"Button": { | |
top : 20, | |
left : 50, | |
right : 50, | |
height: 40, | |
title: "Prendre ou choisir un vidéo" | |
} | |
"TextArea": { | |
borderColor: "orange", | |
editable: false, | |
top : 20, | |
bottom: 10, | |
left : 20, | |
right: 20, | |
font: { | |
fontSize: 14 | |
}, | |
color: "black" | |
} | |
"#videoPlayer": { | |
height: 200, | |
left : 20, | |
right : 20, | |
backgroundColor: "black" | |
} | |
"#user": { | |
hintText: 'userid' | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<Alloy> | |
<Window class="container"> | |
<ScrollView> | |
<View id="videoPlayer" top="20" layout="vertical" /> | |
<TextField id="txt" /> | |
<TextField id="user" /> | |
<Button onClick="takeVideo" /> | |
<TextArea id="log"></TextArea> | |
</ScrollView> | |
</Window> | |
</Alloy> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment