Skip to content

Instantly share code, notes, and snippets.

@chmiiller
Forked from SquirrelMobile/alloy.js
Created January 30, 2018 14:47
Show Gist options
  • Save chmiiller/0b51e5a19f1a9cf63af85d81be5dd0e2 to your computer and use it in GitHub Desktop.
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
//Download and install widget loader : https://github.com/FokkeZB/nl.fokkezb.loading
Alloy.Globals.loading = Alloy.createWidget("nl.fokkezb.loading");
{
"global": {},
"env:development": {},
"env:test": {},
"env:production": {},
"os:android": {},
"os:ios": {},
"os:windows": {},
"dependencies": {
"nl.fokkezb.loading": "*"
}
}
<?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>
$.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;
}
<?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);
}
}
?>
".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'
}
<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