顯示具有 upload 標籤的文章。 顯示所有文章
顯示具有 upload 標籤的文章。 顯示所有文章

2017年5月21日 星期日

[PHP] 使用 AWS SDK 進行 S3 檔案上傳

寫過又忘了,筆記一下,環境是 PHP 5.5.9:

<?php
require 'aws.phar'; // http://docs.aws.amazon.com/aws-sdk-php/v3/download/aws.phar //aws-3.27.5.phar
$s3 = Aws\S3\S3Client::factory(array(
'region' => 'us-west-2',
// http://docs.aws.amazon.com/aws-sdk-php/v3/api/index.html
'version' => '2006-03-01',
'credentials' => array(
'key' => 'key',
'secret' => 'secret',
),
        ));

try {
$result = $s3->putObject(array(
'Bucket' => 'my-bucket',
'Key' => 'my-object-key'
'SourceFile' => $_FILES['userfile']['tmp_name'],
        ));
} catch (Exception $e) {
             
echo $e->getMessage() . "\n";
}

print_r($result);
// $result['ObjectURL'];


Aws\Result Object
(
    [data:Aws\Result:private] => Array
        (
            [Expiration] =>
            [ETag] =>
            [ServerSideEncryption] =>
            [VersionId] =>
            [SSECustomerAlgorithm] =>
            [SSECustomerKeyMD5] =>
            [SSEKMSKeyId] =>
            [RequestCharged] =>
            [@metadata] => Array
                (
                    [statusCode] => 200
                    [effectiveUri] => https://s3-us-west-2.amazonaws.com/my-bucket/my-object-key
                    [headers] => Array
                        (
                            [x-amz-id-2] =>
                            [x-amz-request-id] =>
                            [date] =>
                            [etag] =>
                            [content-length] => 0
                            [server] => AmazonS3
                        )

                    [transferStats] => Array
                        (
                            [http] => Array
                                (
                                    [0] => Array
                                        (
                                        )

                                )

                        )

                )

            [ObjectURL] => https://s3-us-west-2.amazonaws.com/my-bucket/my-object-key
        )

)

2016年10月9日 星期日

iOS 開發筆記 - 建立/更新 Apple Push Notification Service (APNs) 憑證、P12轉PEM、驗證 PEM、PHP 範例程式

APNs_export_key

以前寫過幾篇 APNs 筆記,但好像都沒很完整,結果每年要更新憑證時,都要再找資料複習一次 Orz 所以就把它筆記下來吧!
首先,在 iOS Developer 網站上可以維護 APNs 憑證,然而,一旦過期,其實會自動消失 Orz 而 APNs 這服務滿像開發一次後就一直擺在那,沒用行事曆紀錄肯定忘掉。

如果,當初的 Certificate Signing Request (CSR) 以及 private key(.p12) 還留著的話,可以繼續拿來用,若沒有的話,就重新建立。整個就像第一次建立一樣 :P

Step 1:

iOS Developer Website -> Certificate -> All -> [+] -> Production -> Apple Push Notification service SSL (Sandbox & Production) -> App ID: -> Your App ID -> About Creating a Certificate Signing Request (CSR) -> Upload CRS file

若之前的 CSR 跟 p12 都還在,就可以省去製作 CSR,直接拿舊的上傳;若要新建立就從 Keychain -> 憑證輔助程式 -> 從憑證授權要求憑證 -> 輸入 email -> 預設將產生 CertificateSigningRequest.certSigningRequest 檔案,把他拿去上傳吧。另外,記得要把下載到的 aps.cer 點擊匯入至 keychain 中。

Step 2:

在 keychain -> 類別 -> 我的憑證 -> 可以看到 Apple Push Service 資訊,展開後,點擊專用密鑰,在點擊上方的憑證後,可以以憑證為單位輸出 p12 資料,這是跟 APN server 溝通的通行證。

Step 3:

使用 openssl 將通行證轉檔,從 p12 成 pem 檔

$ openssl pkcs12 -in App.p12 -out App.pem -nodes

轉換後,可以用文字編輯器打開 App.pem 檔案,會看到兩段:

-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
...
-----END PRIVATE KEY-----


而 CERTIFICATE 上頭也會標記是哪個 App ID 的,未來忘記都可以翻來看

Step 4:

做簡單的 pem 驗證即可。

Production:

$ openssl s_client -connect gateway.push.apple.com:2195 -cert App.pem

Sandbox:

$ openssl s_client -connect gateway.sandbox.push.apple.com:2195 -cert App.pem

若 pem 是正常的,應該連線完就停在那邊:

...
---
SSL handshake has read 3385 bytes and written 2515 bytes
---
New, TLSv1/SSLv3, Cipher is AES256-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : AES256-SHA
    Session-ID:
    Session-ID-ctx:
    Master-Key: #######
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    Start Time: 1476026971
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)
---
^C


Step 5:

可以拿 pem 跟 APNs 互動了!以下是片段 PHP 程式碼,有興趣可再試試 changyy/codeigniter-library-notification 包好的 library。

<?php

$ssl_ctx = stream_context_create();
stream_context_set_option($ssl_ctx, 'ssl', 'local_cert', $pem_file_path);

if( is_resource( $fp = stream_socket_client(
$use_sansbox ? 'ssl://gateway.sandbox.push.apple.com:2195' : 'ssl://gateway.push.apple.com:2195',
$err,
$errstr,
60,
STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT,
$ssl_ctx
) ) ) {

//$payload = array(
// 'aps' => array(
// 'alert' => array(
// 'title' => $title,
// 'body' => $message,
// )
// )
//);

$packed_data =
// Command (Simple Notification Format)
chr(0)
// device token
. pack('n', 32) . pack('H*', $notification_token)
// payload
//. pack('n', strlen($raw_cmd)) . $raw_cmd;
. $raw_data;

if( @fwrite($fp, $packed_data, strlen($packed_data)) !== false ) {
echo "SUCCESS";
} else {
echo "FAILURE";
}

fclose($fp);
}

2015年9月27日 星期日

[GO] 使用 Go drive 同步資料至 Google Drive 空間 @ Ubuntu 14.04 64bit

之前默默地得到 Google for edu 的帳號,想說該善用一下空間。之前比較常用 Dropbox 的空間,所以一直沒善用 Google Drive ,但是埋在 Linode 1GB 機器上,常常覺得記憶體都被 Dropbox 吃光,這次就試試 Google drive 吧!有 1TB 的空間,就拿來備份服務產生的資料了 cc

接著,找了很久,才發現有一個用 Go 語言寫的 Google drive 指令,接著想說用 apt-get 安裝 go 語言,結果版本不夠新,又找了 gvm 來試試,總之,流程如下:
  1. 安裝 gvm
  2. 安裝編譯 golang 所需套件
  3. 安裝 drive
  4. 編輯 .bashrc 環境變數
  5. 初始化 google drive
  6. 上傳資料至 google drive
連續動作:

$ bash < <(curl -s -S -L https://raw.githubusercontent.com/moovweb/gvm/master/binscripts/gvm-installer)
$ gvm install go1.5 --binary
$ vim .bashrc
export GOPATH="$HOME/go-package”
export PATH=$PATH:$GOPATH/bin
$ go get -u github.com/odeke-em/drive/cmd/drive
$ mkdir $HOME/gdrive
$ drive init $HOME/gdrive


未來在 $HOME/gdrive 建立完資料,可以用 drive push path 來進行上傳到 Google Drive。接著就偷懶把指令擺在 crontab 啦,要留意 gvm 的使用,如:

*/20    *       *       *       *       bash -c 'source $HOME/.gvm/scripts/gvm && gvm use go1.5 && cd $HOME/gdrive && drive push -no-prompt -quiet test_auto_upload_dir/‘ > /dev/null

同理,若真的要做到 sync 的話,可以再用 drive pull test_auto_upload_dir 來更新更動,而把 sync 動作切該成 drive push 跟 drive pull 也有好處,例如可製作永遠上傳至 google drive 的功能,同時也能定期刪掉已上傳過的資料!

2015年2月12日 星期四

AWS 筆記 - 使用 AWS Glacier 服務備份大量資料 @ Ubuntu 14.04

這個服務大概 2014 年夏天就開始關注並且在秋天嘗試使用,曾經也寫過一篇筆記但...最後沒發表 XD 實在是 AWS Glacier 如其名,大部份的指令真的像冰河緩慢移動 Orz 接著忙了就忘了。這次下定決心來寫一篇筆記。

簡言之,費用比 AWS S3 便宜,但是存取 AWS Glacier 的行為更像傳統磁帶模式,很多操作動作,會先給你一個 Job ID,還得手動用此 ID 去確認結果。例如想查閱已經有多少檔案,會發一個需求 Job ID 給你,而非馬上跟你說已經有多少檔案了。

整體上,要上傳資料一定要走 AWS API 方式,也就是到 AWS IAM 上建立一個 user,給予以下權限:
  • Amazon Glacier Full Access (另一個則是 Amazon Glacier Read Only Access)
  • Amazon SQS Full Access (下載檔案會用到, 若工作僅上傳則不需要, 沒有時的錯誤訊息: Access to the resource https://sqs.ap-northeast-1.amazonaws.com/ is denied)
  • Amazon SNS Full Access (下載檔案會用到, 若工作僅上傳則不需要, 沒有時的錯誤訊息: User: arn:aws:iam::####:user/#### is not authorized to perform: SNS:CreateTopic on resource)
我記得去年摸時,是使用 Amazon SimpleDB (sdb:*) 相關的權限,印象中跟 metadata 有關,不過現在卻沒查到了?! :P 接著,替使用者建立一組 access key/ secret key 來使用,而往後的上傳、下載等是靠這組 API KEY 工作。

此外,使用 AWS Glacier 前,要稍微瞭解一下操作方式
  • 不同的 Data Center 會因為電價等關係,所以儲存的費用不一樣。
  • 上傳資料前,除了要挑選 Data Center 外,還需要類似建立一個類似目錄的儲存單位 (Vault)
  • 除了網頁版 GUI 可以進行 Create Vault, Delete Vault 外,其餘都一律透過 API 進行,其中 Delete Vault 還必須確定裡頭沒其他檔案
  • 透過 API 操作時,需要的基本參數為 API KEY、Data Center (region/endpoint) 等資料
雖然用過 python 版工具 https://github.com/uskudnik/amazon-glacier-cmd-interface,這次就來用用 Java 版吧!https://github.com/MoriTanosuke/glacieruploader

建立 Vault (可透過 AWS Web Console)操作:

$ java -jar uploader-0.0.8-SNAPSHOT-jar-with-dependencies.jar -e "https://glacier.ap-northeast-1.amazonaws.com" -v changyy-vault -c
INFO  Using end point: https://glacier.ap-northeast-1.amazonaws.com
INFO  Creating vault changyy-vault...
INFO  Vault changyy-vault created. {Location: /##########/vaults/changyy-vault}
LastInventoryDate: null
NumberOfArchives: 0
SizeInBytes: 0
VaultARN: arn:aws:glacier:ap-northeast-1:##########:vaults/changyy-vault
VaultName: changyy-vault


上傳檔案(最後的 archive 接的資料就是該筆料的 ID):

$ java -jar uploader-0.0.8-SNAPSHOT-jar-with-dependencies.jar -e "https://glacier.ap-northeast-1.amazonaws.com" -v changyy-vault --upload ~/uploader-0.0.8-SNAPSHOT-jar-with-dependencies.jar
INFO  Using end point: https://glacier.ap-northeast-1.amazonaws.com
INFO  Starting to upload $HOME/uploader-0.0.8-SNAPSHOT-jar-with-dependencies.jar to vault changyy-vault...
INFO  Uploaded archive ########################################


切檔上傳,此例是 128MB 為單位,適合檔案很大的情境(Archive ID 接的資料就是該筆料的 ID):

$ java -jar uploader-0.0.8-SNAPSHOT-jar-with-dependencies.jar -e "https://glacier.ap-northeast-1.amazonaws.com" -v changyy-vault --upload ~/uploader-0.0.8-SNAPSHOT-jar-with-dependencies.jar --multipartupload ~/TargetBigFile --partsize 134217728
INFO  Using end point: https://glacier.ap-northeast-1.amazonaws.com/
INFO  Multipart uploading TargetBigFile to vault changyy-vault with part size 134217728 (128.00MB).
INFO  Upload ID (token): ################################################
INFO  Part 1/187 (bytes 0-134217727/*) uploaded, checksum: e19319be5e3c5d3f45a1ce7ef9ab3644b6933ec01c0754285babf45eb46b5b0b
...
INFO  Part 187/187 (bytes 24964497408-24993715534/*) uploaded, checksum: d0219f53b4f54431495211bfd8880fe52597354acc51aa077dcb67cacee69f53
INFO  Uploaded Archive ID: ################################################
INFO  Local Checksum: a1500723e11892cc2bb297d5d6f97a08035e30810ae0e3342184fbed4e2c2d5b
INFO  Remote Checksum: a1500723e11892cc2bb297d5d6f97a08035e30810ae0e3342184fbed4e2c2d5b
INFO  Checksums are identical, upload succeeded.


然而,剛上傳完是無法馬上下載的 :P 而想要查詢檔案列也是,必須先發一個"查詢列表"的工作(得到 Job ID),等工作結束後才能查詢到結果(取得檔案列表)

發出"查詢 Vault 檔案列表"的需求:

$ java -jar uploader-0.0.8-SNAPSHOT-jar-with-dependencies.jar -e "https://glacier.ap-northeast-1.amazonaws.com" -v changyy-vault -l
INFO  Using end point: https://glacier.ap-northeast-1.amazonaws.com
INFO  Starting inventory listing for vault changyy-vault...
INFO  Inventory Job created with ID
8KDBk2AS_9bYC8dIOBHxjitqxaLhEklXPfU6jZO-t-su3cp1k3NaHFIUpFaBiJDXDGFyzYyqaw-3MboGNlJ2W6kKDzmt


若這個 Vault 是剛建立的,還會有類似錯誤訊息:vaults/changyy-vault cannot be initiated yet, as Amazon Glacier has not yet generated an initial inventory for this vault.

取得"查詢 Vault 檔案列表"的結果:

$ java -jar uploader-0.0.8-SNAPSHOT-jar-with-dependencies.jar -e "https://glacier.ap-northeast-1.amazonaws.com" -v changyy-vault -l 8KDBk2AS_9bYC8dIOBHxjitqxaLhEklXPfU6jZO-t-su3cp1k3NaHFIUpFaBiJDXDGFyzYyqaw-3MboGNlJ2W6kKDzmt

若工作未做完,會顯示錯誤訊息:ERROR The job is not currently available for download。做完的話,會顯示清單,其中 Description 在這套 Java 工具下,會自動填寫上傳的檔名:

ARN: arn:aws:glacier:ap-northeast-1:##############:vaults/changyy-vault
------------------------------------------------------------------------------
Description:  uploader-0.0.8-SNAPSHOT-jar-with-dependencies.jar
Archive ID: q_SfW7MNmTE1_9xBbmzP5MvnEGYYmF8wCIe2aYs4_7NAXjn8fEO4nl97QZ-deJ_hDsKni7n5z0avn8gEdAnFfzMV4xE9FlF2Fr3UualyZj0b4LNSq9cENWYWoueSma9Kq8zGuwA9IA
CreationDate: 2015-02-07T11:17:36Z
Size: 19496656 (18.60MB)
SHA: d07cddbcbe3a83dba2b4ca654760bba4b77f92ae1ecc9f1fbffad337730fece0


下載檔案:

$ java -jar uploader-0.0.8-SNAPSHOT-jar-with-dependencies.jar -e "https://glacier.ap-northeast-1.amazonaws.com" -v changyy-vault --download q_SfW7MNmTE1_9xBbmzP5MvnEGYYmF8wCIe2aYs4_7NAXjn8fEO4nl97QZ-deJ_hDsKni7n5z0avn8gEdAnFfzMV4xE9FlF2Fr3UualyZj0b4LNSq9cENWYWoueSma9Kq8zGuwA9IA --target /tmp/test.jar
INFO  Using end point: https://glacier.ap-northeast-1.amazonaws.com
INFO  Downloading archive q_SfW7MNmTE1_9xBbmzP5MvnEGYYmF8wCIe2aYs4_7NAXjn8fEO4nl97QZ-deJ_hDsKni7n5z0avn8gEdAnFfzMV4xE9FlF2Fr3UualyZj0b4LNSq9cENWYWoueSma9Kq8zGuwA9IA from vault changyy-vault...
INFO Archive downloaded to /tmp/test.jar


整個過程不會馬上進入下載 Orz 例如我下載一個 52MB 的檔案,整個過程耗費 245 分鐘...絕對不是下載速度太慢,而是準備流程要等好一陣子。

刪除檔案:

$ java -jar uploader-0.0.8-SNAPSHOT-jar-with-dependencies.jar -e "https://glacier.ap-northeast-1.amazonaws.com" -v changyy-vault --delete q_SfW7MNmTE1_9xBbmzP5MvnEGYYmF8wCIe2aYs4_7NAXjn8fEO4nl97QZ-deJ_hDsKni7n5z0avn8gEdAnFfzMV4xE9FlF2Fr3UualyZj0b4LNSq9cENWYWoueSma9Kq8zGuwA9IA
INFO  Using end point: https://glacier.ap-northeast-1.amazonaws.com
INFO  Deleting archive q_SfW7MNmTE1_9xBbmzP5MvnEGYYmF8wCIe2aYs4_7NAXjn8fEO4nl97QZ-deJ_hDsKni7n5z0avn8gEdAnFfzMV4xE9FlF2Fr3UualyZj0b4LNSq9cENWYWoueSma9Kq8zGuwA9IA from vault changyy-vault...
INFO  Archive q_SfW7MNmTE1_9xBbmzP5MvnEGYYmF8wCIe2aYs4_7NAXjn8fEO4nl97QZ-deJ_hDsKni7n5z0avn8gEdAnFfzMV4xE9FlF2Fr3UualyZj0b4LNSq9cENWYWoueSma9Kq8zGuwA9IA deletion started from vault changyy-vault.


刪除 Vault:

$ java -jar uploader-0.0.8-SNAPSHOT-jar-with-dependencies.jar -e "https://glacier.ap-northeast-1.amazonaws.com" -v changyy-vault --delete-vault
INFO  Using end point: https://glacier.ap-northeast-1.amazonaws.com
INFO  Deleting vault changyy-vault...


若 vault 內還有檔案會有錯誤訊息:Vault not empty or recently written to: arn:aws:glacier:ap-northeast-1:############:vaults/changyy-vault。此外,若先去刪檔案,再來執行也會有一樣的問題,因為這是冰川啊 XD 刪檔也是慢慢地

整體心得,AWS Glacier 操作上真的很煩,因為太慢了。此外,也必須把那些 File Archive ID 記好,或是任何工作的 Job ID 記好,後續才能工作。有興趣可以在玩看看視窗介面,例如 CrossFTP 等,在操作檔案列表時,會跟你說要數小時(>5小時)才會得知結果,唯一的好處就是 CrossFTP 會幫你把一些 Job ID 記住吧