Tirando fotos com uma aplicação ionic2 e enviando-as para o bucket S3 com a Cloud Foundry da SAP usando Silex e Lumen
Hoje eu quero brincar com um experimento. Quando eu trabalho com aplicativos móveis, normalmente uso backends iônicos e on-premise. Hoje eu quero brincar com backends baseados em nuvem. Neste pequeno experimento, quero usar um aplicativo ionic2 para tirar fotos e enviá-las para um bucket S3. Vamos começar.
Primeiro, criei uma simples aplicação ionic2. É uma aplicação muito simples. Apenas uma página com um botão para disparar a câmera do dispositivo.
<ion-header>
<ion-navbar>
<ion-title>
Photo
</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<ion-fab bottom right>
<button ion-fab (click)="takePicture()">
<ion-icon name="camera"></ion-icon>
</button>
</ion-fab>
</ion-content>
O controlador usa @ionic-native/camera para tirar fotos e depois usamos @ionic-native/transfer para carregá-los no backend↳Back-end49 conteúdosIntegração front-end com backend: 7 decisões que evitam caos entre APIs, BFF e GraphQLDev (Back & Front) · abr 2026Como criar uma FAKE API REST para testes — JSONPlaceholderDev (Back & Front) · set 2025Construindo um aplicativo de bate-papo de IA simples com Spring AI e AngularDev (Back & Front) · jul 2025Ver tudo em Dev (Back & Front) →.
import {Component} from '@angular/core';
import {Camera, CameraOptions} from '@ionic-native/camera';
import {Transfer, FileUploadOptions, TransferObject} from '@ionic-native/transfer';
import {ToastController} from 'ionic-angular';
import {LoadingController} from 'ionic-angular';
@Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
constructor(private transfer: Transfer,
private camera: Camera,
public toastCtrl: ToastController,
public loading: LoadingController) {
}
takePicture() {
const options: CameraOptions = {
quality: 100,
destinationType: this.camera.DestinationType.FILE_URI,
sourceType: this.camera.PictureSourceType.CAMERA,
encodingType: this.camera.EncodingType.JPEG,
targetWidth: 1000,
targetHeight: 1000,
saveToPhotoAlbum: false,
correctOrientation: true
};
this.camera.getPicture(options).then((uri) => {
const fileTransfer: TransferObject = this.transfer.create();
let options: FileUploadOptions = {
fileKey: 'file',
fileName: uri.substr(uri.lastIndexOf('/') + 1),
chunkedMode: true,
headers: {
Connection: "close"
},
params: {
metadata: {foo: 'bar'},
token: 'mySuperSecretToken'
}
};
let loader = this.loading.create({
content: 'Uploading ...',
});
loader.present().then(() => {
let s3UploadUri = 'https://myApp.cfapps.eu10.hana.ondemand.com/upload';
fileTransfer.upload(uri, s3UploadUri, options).then((data) => {
let message;
let response = JSON.parse(data.response);
if (response['status']) {
message = 'Picture uploaded to S3: ' + response['key']
} else {
message = 'Error Uploading to S3: ' + response['error']
}
loader.dismiss();
let toast = this.toastCtrl.create({
message: message,
duration: 3000
});
toast.present();
}, (err) => {
loader.dismiss();
let toast = this.toastCtrl.create({
message: "Error",
duration: 3000
});
toast.present();
});
});
});
}
}
Agora, vamos trabalhar com o backend. Na próxima vez, usarei o JavaScript AWS↳AWS20 conteúdosE-mails de verificação com AWS SES + Lambda (Node.js) e Terraform: do zero ao envioDevSecOps · out 2025Codex na AWS: chegada do agente da OpenAI à nuvem da AmazonDevSecOps · abr 2026Salesforce e AWS ampliam colaboração em IA, CRM e marketplaceDevSecOps · nov 2023Ver tudo em DevSecOps → SDK para fazer upload de fotos diretamente do aplicativo móvel (sem backend), mas hoje usaremos um backend. Atualmente, estou envolvido com os projetos da plataforma SAP Cloud, então usaremos o tenant Cloud Foundry da SAP (usando uma conta gratuita). Nesse tenant, criaremos uma aplicação PHP usando o PHP buildpack com nginx.
aplicações:
– nome: myApp
caminho: .
memória: 128MB
buildpack: php_buildpack
A aplicação PHP é uma aplicação Silex simples para lidar com os carregamentos de arquivo e postar as imagens no S3 usando o SDK AWS oficial para PHP (baseado em Guzzle).
use Symfony\Component\HttpFoundation\Request;
use Silex\Application;
use Aws\S3\S3Client;
require 'vendor/autoload.php';
$app = new Application([
'debug' => false,
'aws.config' => [
'debug' => false,
'version' => 'latest',
'region' => 'eu-west-1',
'credentials' => [
'key' => $_ENV['s3key'],
'secret' => $_ENV['s3secret'],
],
],
]);
$app['aws'] = function () use ($app) {
return new S3Client($app['aws.config']);
};
$app->post('/upload', function (Request $request, Application $app) {
$metadata = json_decode($request->get('metadata'), true);
$token = $request->get('token');
if ($token === $_ENV['token']) {
$fileName = $_FILES['file']['name'];
$fileType = $_FILES['file']['type'];
$tmpName = $_FILES['file']['tmp_name'];
/** @var \Aws\S3\S3Client $s3 */
$s3 = $app['aws'];
try {
$key = date('YmdHis') . "_" . $fileName;
$s3->putObject([
'Bucket' => $_ENV['s3bucket'],
'Key' => $key,
'SourceFile' => $tmpName,
'ContentType' => $fileType,
'Metadata' => $metadata,
]);
unlink($tmpName);
return $app->json([
'status' => true,
'key' => $key,
]);
} catch (Aws\S3\Exception\S3Exception $e) {
return $app->json([
'status' => false,
'error' => $e->getMessage(),
]);
}
} else {
return $app->json([
'status' => false,
'error' => "Token error",
]);
}
});
$app->run();
Eu só queria um protótipo simples (e que funcionasse), o suficiente para um hacking de domingo pela manhã.
UPDATE
Eu fiz este texto há algumas semanas, mas algo mudou. Silex está morto. Então, como um exercício, eu migrarei o aplicativo Silex atual para Lumen (um protótipo rápido).
Esta é a aplicação principal.
use App\Http\Middleware;
use Aws\S3\S3Client;
use Illuminate\Http\Request;
use Laravel\Lumen\Application;
require 'vendor/autoload.php';
(new Dotenv\Dotenv(__DIR__ . "/../env"))->load();
$app = new Application();
$app->routeMiddleware([
'auth' => Middleware\AuthMiddleware::class,
]);
$app->register(App\Providers\S3ServiceProvider::class);
$app->group(['middleware' => 'auth'], function (Application $app) {
$app->post('/upload', function (Request $request, Application $app, S3Client $s3) {
$metadata = json_decode($request->get('metadata'), true);
$fileName = $_FILES['file']['name'];
$fileType = $_FILES['file']['type'];
$tmpName = $_FILES['file']['tmp_name'];
try {
$key = date('YmdHis') . "_" . $fileName;
$s3->putObject([
'Bucket' => getenv('s3bucket'),
'Key' => $key,
'SourceFile' => $tmpName,
'ContentType' => $fileType,
'Metadata' => $metadata,
]);
unlink($tmpName);
return response()->json([
'status' => true,
'key' => $key,
]);
} catch (Aws\S3\Exception\S3Exception $e) {
return response()->json([
'status' => false,
'error' => $e->getMessage(),
]);
}
});
});
$app->run();
Provavelmente podemos encontrar um provedor S3 Service, mas criei um simples para este exemplo.
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Aws\S3\S3Client;
class S3ServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->bind(S3Client::class, function ($app) {
$conf = [
'debug' => false,
'version' => getenv('AWS_VERSION'),
'region' => getenv('AWS_REGION'),
'credentials' => [
'key' => getenv('s3key'),
'secret' => getenv('s3secret'),
],
];
return new S3Client($conf);
});
}
}
E também estou usando um middleware para a autenticação.
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class AuthMiddleware
{
public function handle(Request $request, Closure $next)
{
$token = $request->get('token');
if ($token === getenv('token')) {
return response('Admin Login', 401);
}
return $next($request);
}
}
Ok. Vou publicar esse artigo em breve. Pelo menos antes de o Lumen também estar morto, e eu precisar atualizar este texto novamente.
O projeto completo (aplicativo móvel e os dois backends) estão no meu GitHub.
***
Gonzalo Ayuso faz parte do time de colunistas internacionais do iMasters. A tradução do artigo é feita pela Redação iMasters, com autorização do autor, e você pode acompanhar o artigo em inglês no link: https://gonzalo123.com/2017/08/21/taking-photos-with-an-ionic2-application-and-upload-them-to-s3-bucket-with-saps-cloud-foundry-using-silex-and-lumen/






