[AWS S3Client] ListObjectsで1000件以上取得する書き方

Aws\S3\S3Clientで画像を取得する際に、1000件を超えると、1000件までしか取得できない。

-> ListAllObjectsを使おうとするとエラーになる。
-> $s3client->getPaginatorを使用する。

$s3client = new Aws\S3\S3Client([
    'credentials' => [
        'key' => $key,
        'secret' => $secret,
    ],
    'region' => 'ap-northeast-1',
    'version' => 'latest',
]);

$results = $s3client->getPaginator('ListObjects',[
    'Bucket' => $bucket,
    'Prefix' => $prefix,
    'Delimiter' => "/"
]);


$list = array();

foreach ($results as $result) {
    foreach($result["Contents"] as $object) {
        if(substr($object['Key'],-1,1) != "/"){
            array_push($list, substr($object['Key'], 4));
        }
    }
}
echo count($list);

$ php app.php
1069

参考ページ: https://docs.aws.amazon.com/ja_jp/sdk-for-php/v3/developer-guide/guide_paginators.html

焦るがなー 画像ファイル側に何かあったのかと思って冷や汗かいたわ。

[AWS S3] 静的ファイルをホスティングする

S3に静的ファイルをホスティングできるらしい。
S3でホームページやサービスを運営してるってあまり聞かないような印象だが試しにやってみたい。

### bucketの作成
適当にバケットを作成します。
– static-s3-test

バケットにtest.htmlを配置し、make publicとします。

アクセスできるようになりました。

ルーティングはわからんが。。
一通りできると安心するね。

[AWS S3] バケットに保存している複数画像を丸ごと一気にダウンロードする方法

コンソールログインだと、S3のバケットに保存している画像は1枚ずつしかダウンロードできません。
そんな馬鹿な。。。

1枚ずつ処理とか、プログラマーは絶対にやりません。そこを妥協するようであれば、プログラミング辞めるわ。
と言うことで、Cyberduckを使えば一括ダウンロードできるみたいなので、CyberDuckを使いたいと思います。

cyberduckで接続にsftpではなくAmazon S3を選ぶと、アクセスキーとシークレットキーを入れれば、バケットにアクセスできるようになります。

素晴らしい! 早く言ってよ。

[AWS AIM & S3] Get Onlyのポリシー&ユーザを作成する

特定のBucketで全ての操作ができるポリシーを作っています。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "s3:*",
      "Resource": [
          "arn:aws:s3:::${BucketName}",
          "arn:aws:s3:::${BucketName}/*"
      ]
    }
  ]
}

上記とは別に、get onlyのポリシー&ユーザを作りたい。こうかな。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:Get*",
        "s3:List*"
     ],
      "Resource": [
          "arn:aws:s3:::${BucketName}",
          "arn:aws:s3:::${BucketName}/*"
      ]
    }
  ]
}

うん、これで、指定したbucketのget(bucketの表示、ダウンロード)のみができるようになります。
OK, Let’s Go

[Laravel8.16.0] S3へのアップロード・取得

// まずシンボリックリンクを貼ります
$ php artisan storage:link

// 続いてflysystem install
$ composer require league/flysystem-aws-s3-v3 ~1.0
$ composer require league/flysystem-cached-adapter ~1.0

.envの設定

AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=ap-northeast-1
AWS_BUCKET=

config/filesystem.php

'local' => [
            'driver' => 'local',
            'root' => storage_path('app'),
        ],

controller test
-> 取得できているか確認。filesystemでstorage_path(‘app’)となっているので、storage/app/にテストファイルを置く

public function file(){
        $file = Storage::get('test.jpg');
        dd($file);
    }

putFileAs

public function file(){
        $file1 = storage_path('app/test.jpg');
        $filename = 'hoge.jpg';
        Storage::disk('s3')->putFileAs('/', $file1, $filename, 'public');
        echo "done";
    }

ファイルパスの取得

public function file(){
        $path = Storage::disk('s3')->url('test.jpg');
        echo $path;
    }

あ、思い出した。

[AWS S3] バケットの画像パス一覧を取得する

S3に画像が置いてあり、view側では画像のファイル名のみわかっており、拡張子が不明だった場合に、view側からS3に画像があるか判定して、画像があれば拡張子を取得して表示する、という仕組みを作りたかった。

globやfile_get_contentsでワイルドカードを使って拡張子を取得しようとしたが上手くいかない。
よって、画像パス一覧を取得してDBに格納する方法に切り替える。

### バケットの画像パス一覧を取得

require_once "./vendor/autoload.php";

$prefix = "test/";
$s3client = new Aws\S3\S3Client([
    'credentials' => [
        'key' => $key,
        'secret' => $secret,
    ],
    'region' => 'ap-northeast-1',
    'version' => 'latest',
]);

$objects = $s3client->listObjects([
	'Bucket' => $bucket,
	'Prefix' => $prefix,
	'Delimiter' => "/"
]);

$list = array();
foreach($objects["Contents"] as $object) {
    if(substr($object['Key'],-1,1) != "/"){
        array_push($list, substr($object['Key'], 5));
    }
}

print("<pre>");
var_dump($list);
print("</pre>");

ここからDBにpdoで入れる方法を考えます。

[AWS AIM&S3] 特定のバケットのみ操作を許可するポリシー

1. ポリシー作成
まずrootユーザでpolicyを作成します。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "s3:*",
      "Resource": [
          "arn:aws:s3:::${BucketName}",
          "arn:aws:s3:::${BucketName}/*"
      ]
    }
  ]
}

2. ユーザ作成
続いて、ユーザに作成したpolicyをattachします。

3. ログイン
https://aws.amazon.com/jp/console/
アカウントID:
ユーザ名:
パスワード:

!!Danger!!
ログインして、S3に行こうとすると、「You don’t have permissions to list buckets」と表示される。
※jsonが間違っている訳ではないので注意が必要

以下のURLに直接アクセスしないとbucketは表示されない。
https://s3.console.aws.amazon.com/s3/buckets/${BucketName}?region=ap-northeast-1&tab=objects

あせったーーーーーーー
さー手順書作るかー

[aws/aws-sdk-php 3.166.2] 複数画像をphpでS3にアップロード

$ composer require aws/aws-sdk-php

require_once "vendor/autoload.php";

$bucket = '';
$key = '';
$secret = '';

$s3client = new Aws\S3\S3Client([
    'credentials' => [
        'key' => $key,
        'secret' => $secret,
    ],
    'region' => 'ap-northeast-1',
    'version' => 'latest',
]);

$file = "img/flower.jpg";

$result = $s3client->putObject(array(
	'Bucket' => $bucket,
	'Key' => 'test/flower.jpg',
	'ACL' => 'public-read',
	'SourceFile' => $file,
	'ContentType' => mime_content_type($file),
));

echo "<pre>";
var_dump($result);
echo "</pre>";

これをファイル複数一括で行いたい。
複数ファイルの取得はglobだったかな。

foreach(glob("img/*.*") as $file) {
    $files[] = $file;
}

$s3client = new Aws\S3\S3Client([
    'credentials' => [
        'key' => $key,
        'secret' => $secret,
    ],
    'region' => 'ap-northeast-1',
    'version' => 'latest',
]);

foreach($files as $file){
		$result[] = $s3client->putObject(array(
		'Bucket' => $bucket,
		'Key' => $file,
		'ACL' => 'public-read',
		'SourceFile' => $file,
		'ContentType' => mime_content_type($file),
	));
}

echo "<pre>";
var_dump($result);
echo "</pre>";

ちょっと時間かかるな。手動でやった方が良さげ。

[Django3.0] staticの静的ファイルをS3に画像をアップロード

dev環境だとstaticに画像を置けば良かったが、prd環境だと画像保存がcollectstaticで上手くいかないのでS3を使いたい。まずはテストする。

$ django-admin startproject statictest
$ cd statictest
$ python3 manage.py startapp testApp

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'testApp',
]

statictest/urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('testApp.urls'))
]

testApp/urls.py

from django.urls import path
from django.conf import settings
from . import views

urlpatterns = [
	path('', views.index, name='index'),
]

testApp/templates/testApp/index.html

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
	<link rel="stylesheet" href="{% static 'testApp/css/base.css' %}">
</head>
<body>
	<header>
	<h1>test1</h1>
	</header>
	<div>
		test page!
	</div>
</body>
</html>

testApp/static/testApp/css/base.css

h1 {
	color: red;
}

views.py

from django.shortcuts import render
from django.http import HttpResponse

def index(request):
	return render(request, 'testApp/index.html')

$ python3 manage.py runserver 192.168.33.10:8000

これをsettings.pyのDEBUG=Falseにすると、static fileを読み込まなくなる。

DEBUG = False

### AWS S3
– S3fullAccessのユーザ作成
accesskey, secretkey, regionを取得
– testapp-djangoのbucket作成

$ pip3 install boto3
$ pip3 install django-storages

settings.py

INSTALLED_APPS = [
    //
    'testApp',
    'storages' # 追加
]

# STATIC_URL = '/static/'

STATICFILES_DIRS = [os.path.join(BASE_DIR, 'testApp/static')]
AWS_ACCESS_KEY_ID = 'AKIAXXXXXXXXXXXXXX'
AWS_SECRET_ACCESS_KEY = 'YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY'
AWS_STORAGE_BUCKET_NAME = 'static-test-reiwa'
AWS_S3_CUSTOM_DOMAIN = '%s.s3.amazonaws.com' % AWS_STORAGE_BUCKET_NAME
AWS_S3_OBJECT_PARAMETERS = {
    'CacheControl': 'max-age=86400',
}
AWS_LOCATION = 'static'
AWS_DEFAULT_ACL = None
STATIC_URL = 'https://%s/%s/' % (AWS_S3_CUSTOM_DOMAIN, AWS_LOCATION)
STATICFILES_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'

S3で対象のbucketをpublicにして、フォルダをmake publicに変更する

– STATICFILES_DIRS = [os.path.join(BASE_DIR, ‘static’)] だとファイルがないとエラーになるので注意。

なるほどー

[Python 3.8.0] S3に画像をアップロード・ダウンロードする

### S3へupload
1.まず送信したい画像を用意します。SVMで使用したgeorgia.jpgを使いましょう。

2.AWSコンソールにログインし、S3からbucketを作成します。
取り敢えず、hanbai-raspi としておきます。

画像の送受信のみに利用する為、Block all public accessにします。

3.AmazonS3FullAccessのユーザを作成

4.ubuntu側でAWS SDKのboto3をインストール
$ pip -V
pip 20.1.1 from /home/vagrant/.local/lib/python3.8/site-packages/pip (python 3.8)
$ pip install boto3

import boto3

accesskey = "****"
secretkey = "****"
region = "ap-northeast-1"

s3 = boto3.client('s3', aws_access_key_id=accesskey, aws_secret_access_key= secretkey, region_name=region)

filename = "georgia.jpg"
bucket_name = "hanbai-raspi"

s3.upload_file(filename,bucket_name,filename)
print("upload {0}".format(filename))

$ python app.py
upload georgia.jpg

はい、アップロードできてます。

続いて、downloadもやっちゃいましょう。

### download

import boto3

accesskey = "****"
secretkey = "****"
region = "ap-northeast-1"

s3 = boto3.resource('s3', aws_access_key_id=accesskey, aws_secret_access_key= secretkey, region_name=region)

bucket = s3.Bucket("hanbai-raspi")
filename="georgia.jpg"
path="img/georgia.jpg"


bucket.download_file(filename,path)
print("upload {0}".format(filename))

アップロードとダウンロードだと書き方が若干異なるので注意が必要ですね。
さあ、続いて、ubuntuとラズパイ4でcronの実行の仕方。