Skip to content

Commit 2b76f0c

Browse files
committed
✨ Initial
1 parent 49a785f commit 2b76f0c

File tree

11 files changed

+361
-0
lines changed

11 files changed

+361
-0
lines changed

.gitattributes

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Path-based git attributes
2+
# https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html
3+
4+
# Ignore all test and documentation with "export-ignore".
5+
/.gitattributes export-ignore
6+
/.gitignore export-ignore
7+
/.travis.yml export-ignore
8+
/phpunit.xml.dist export-ignore
9+
/.scrutinizer.yml export-ignore
10+
/tests export-ignore
11+
/.editorconfig export-ignore

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
build
2+
composer.lock
3+
docs
4+
vendor
5+
coverage

README.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Laravel S3 Browser Based Uploads
2+
3+
[![Latest Version on Packagist](https://img.shields.io/packagist/v/hassan/laravel-s3-browser-based-uploads.svg?style=flat-square)](https://packagist.org/packages/hassan/laravel-s3-browser-based-uploads)
4+
[![Total Downloads](https://img.shields.io/packagist/dt/hassan/laravel-s3-browser-based-uploads.svg?style=flat-square)](https://packagist.org/packages/hassan/laravel-s3-browser-based-uploads)
5+
6+
Upload files to AWS S3 Directly from Browser
7+
8+
## Installation
9+
10+
You can install the package via composer:
11+
12+
```bash
13+
composer require hassan/laravel-s3-browser-based-uploads
14+
```
15+
16+
## Usage
17+
18+
``` php
19+
use Hassan\S3BrowserBasedUploads\Facades\S3BrowserBasedUploads;
20+
21+
S3BrowserBasedUploads::getEndpointUrl()
22+
23+
S3BrowserBasedUploads::getFields()
24+
```
25+
26+
## Example
27+
28+
``` javascript
29+
const formData = new FormData();
30+
31+
@foreach(S3BrowserBasedUploads::getFields() as $key => $value)
32+
formData.append('{{ $key }}', '{{ $value }}');
33+
@endforeach
34+
35+
formData.append('Content-Type', file.type);
36+
formData.append('file', file, file.name);
37+
38+
const request = new XMLHttpRequest();
39+
request.open('POST', "{{ S3BrowserBasedUploads::getEndpointUrl() }}");
40+
request.send(formData);
41+
```
42+
Check out [the demo with Filepond](demo.blade.php)
43+
44+
### Security
45+
46+
If you discover any security related issues, please email [email protected] instead of using the issue tracker.

composer.json

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
{
2+
"name": "hassan/laravel-s3-browser-based-uploads",
3+
"description": "Upload files to AWS S3 Directly from Browser",
4+
"keywords": [
5+
"hassan",
6+
"laravel-s3-browser-based-uploads"
7+
],
8+
"homepage": "https://github.com/hassan/laravel-s3-browser-based-uploads",
9+
"license": "MIT",
10+
"type": "library",
11+
"authors": [
12+
{
13+
"name": "Hassan Ali",
14+
"email": "[email protected]"
15+
}
16+
],
17+
"require": {
18+
"php": "^7.1",
19+
"aws/aws-sdk-php": "^3.0",
20+
"league/flysystem-aws-s3-v3": "^1.0",
21+
"illuminate/support": "5.8.*"
22+
},
23+
"require-dev": {
24+
"orchestra/testbench": "3.8.*",
25+
"phpunit/phpunit": "^7.0"
26+
},
27+
"autoload": {
28+
"psr-4": {
29+
"Hassan\\S3BrowserBasedUploads\\": "src"
30+
}
31+
},
32+
"autoload-dev": {
33+
"psr-4": {
34+
"Hassan\\S3BrowserBasedUploads\\Tests\\": "tests"
35+
}
36+
},
37+
"scripts": {
38+
"test": "vendor/bin/phpunit",
39+
"test-coverage": "vendor/bin/phpunit --coverage-html coverage"
40+
41+
},
42+
"config": {
43+
"sort-packages": true
44+
},
45+
"extra": {
46+
"laravel": {
47+
"providers": [
48+
"Hassan\\S3BrowserBasedUploads\\ServiceProvider"
49+
],
50+
"aliases": {
51+
"S3BrowserBasedUploads": "Hassan\\S3BrowserBasedUploads\\Facades\\S3BrowserBasedUploads"
52+
}
53+
}
54+
}
55+
}

config/config.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
return [
4+
'providers' => [
5+
6+
7+
'default' => [
8+
'disk' => 's3',
9+
'expiration_time' => '+5 minutes',
10+
'inputs' => [],
11+
'conditions' => [
12+
['starts-with', '$key', ''],
13+
['starts-with', '$Content-Type', 'image/'],
14+
['content-length-range', 0, 1000000],
15+
],
16+
],
17+
18+
19+
],
20+
];

demo.blade.php

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1">
6+
<title>Test</title>
7+
8+
<link href="https://unpkg.com/filepond/dist/filepond.css" rel="stylesheet">
9+
</head>
10+
<body>
11+
12+
<input type="file" name="file" id="fileInput">
13+
14+
<script src="https://unpkg.com/filepond/dist/filepond.js"></script>
15+
<script>
16+
const pond = FilePond.create(document.querySelector('input[type="file"]'));
17+
18+
pond.setOptions({
19+
server: {
20+
process:(fieldName, file, metadata, load, error, progress, abort) => {
21+
const formData = new FormData();
22+
23+
@foreach(S3BrowserBasedUploads::getFields() as $key => $value)
24+
formData.append('{{ $key }}', '{{ $value }}');
25+
@endforeach
26+
27+
formData.append('Content-Type', file.type);
28+
formData.append(fieldName, file, file.name);
29+
30+
const request = new XMLHttpRequest();
31+
request.open('POST', "{{ S3BrowserBasedUploads::getEndpointUrl() }}");
32+
33+
request.upload.onprogress = (e) => {
34+
progress(e.lengthComputable, e.loaded, e.total);
35+
};
36+
37+
request.onload = function() {
38+
if (request.status >= 200 && request.status < 300) {
39+
load(request.responseText);
40+
}
41+
else {
42+
error('oh no');
43+
}
44+
};
45+
46+
request.send(formData);
47+
48+
return {
49+
abort: () => {
50+
request.abort();
51+
abort();
52+
}
53+
};
54+
}
55+
}
56+
});
57+
58+
</script>
59+
</body>
60+
</html>

phpunit.xml.dist

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<phpunit bootstrap="vendor/autoload.php"
3+
backupGlobals="false"
4+
backupStaticAttributes="false"
5+
colors="true"
6+
verbose="true"
7+
convertErrorsToExceptions="true"
8+
convertNoticesToExceptions="true"
9+
convertWarningsToExceptions="true"
10+
processIsolation="false"
11+
stopOnFailure="false">
12+
<testsuites>
13+
<testsuite name="Test Suite">
14+
<directory>tests</directory>
15+
</testsuite>
16+
</testsuites>
17+
<filter>
18+
<whitelist>
19+
<directory suffix=".php">src/</directory>
20+
</whitelist>
21+
</filter>
22+
<logging>
23+
<log type="tap" target="build/report.tap"/>
24+
<log type="junit" target="build/report.junit.xml"/>
25+
<log type="coverage-html" target="build/coverage" charset="UTF-8" yui="true" highlight="true"/>
26+
<log type="coverage-text" target="build/coverage.txt"/>
27+
<log type="coverage-clover" target="build/logs/clover.xml"/>
28+
</logging>
29+
</phpunit>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
namespace Hassan\S3BrowserBasedUploads\Facades;
4+
5+
use Illuminate\Support\Facades\Facade;
6+
7+
/**
8+
* @method static string getEndpointUrl()
9+
* @method static array getFields()
10+
*/
11+
class S3BrowserBasedUploads extends Facade
12+
{
13+
/**
14+
* Get the registered name of the component.
15+
*
16+
* @return string
17+
*/
18+
protected static function getFacadeAccessor()
19+
{
20+
return 's3-browser-based-uploads';
21+
}
22+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
namespace Hassan\S3BrowserBasedUploads;
4+
5+
use Aws\S3\PostObjectV4;
6+
use Aws\S3\S3ClientInterface;
7+
8+
class S3BrowserBasedUploadsManager extends PostObjectV4
9+
{
10+
public function __construct(
11+
S3ClientInterface $client,
12+
$bucket,
13+
array $formInputs,
14+
array $options = [],
15+
$expiration = '+1 hours'
16+
) {
17+
$options[] = ['bucket' => $bucket];
18+
19+
parent::__construct($client, $bucket, $formInputs, $options, $expiration);
20+
}
21+
22+
public function getEndpointUrl() : string
23+
{
24+
return $this->getFormAttributes()['action'];
25+
}
26+
27+
public function getFields() : array
28+
{
29+
return $this->getFormInputs();
30+
}
31+
}

src/ServiceProvider.php

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?php
2+
3+
namespace Hassan\S3BrowserBasedUploads;
4+
5+
use Illuminate\Support\ServiceProvider as BaseServiceProvider;
6+
use League\Flysystem\AwsS3v3\AwsS3Adapter;
7+
8+
class ServiceProvider extends BaseServiceProvider
9+
{
10+
/**
11+
* Bootstrap the application services.
12+
*/
13+
public function boot()
14+
{
15+
if ($this->app->runningInConsole()) {
16+
$this->publishes([
17+
__DIR__.'/../config/config.php' => config_path('s3-browser-based-uploads.php'),
18+
], 'config');
19+
}
20+
}
21+
22+
protected function getS3Adapter() : AwsS3Adapter
23+
{
24+
return $this->app['filesystem']->disk($this->getConfig('disk'))->getAdapter();
25+
}
26+
27+
protected function getInputs() : array
28+
{
29+
return $this->getConfig('inputs', []);
30+
}
31+
32+
protected function getConditions() : array
33+
{
34+
return $this->getConfig('conditions', []);
35+
}
36+
37+
protected function getExpirationTime() : string
38+
{
39+
return $this->getConfig('expiration_time', '+5 minutes');
40+
}
41+
42+
public function getConfig(string $key, $default = null)
43+
{
44+
return config('s3-browser-based-uploads.providers.default.' . $key, $default);
45+
}
46+
47+
/**
48+
* Register the application services.
49+
*/
50+
public function register()
51+
{
52+
$this->mergeConfigFrom(__DIR__.'/../config/config.php', 's3-browser-based-uploads');
53+
54+
$this->app->bind(S3BrowserBasedUploadsManager::class, function () {
55+
$adapter = $this->getS3Adapter();
56+
57+
return new S3BrowserBasedUploadsManager(
58+
$adapter->getClient(),
59+
$adapter->getBucket(),
60+
$this->getInputs(),
61+
$this->getConditions(),
62+
$this->getExpirationTime()
63+
);
64+
});
65+
66+
$this->app->alias(S3BrowserBasedUploadsManager::class, 's3-browser-based-uploads');
67+
}
68+
}

0 commit comments

Comments
 (0)