File Upload

檔案上傳 #

流程概況 #

當您操作 SPA 會參考到外部檔案時 (例如提案用圖片、影片),做法為先將檔案上傳至 AWS S3,並將檔案 URL 附加於 SPA 的物件中。

我們提供了取得擁有上傳至我們指定的 S3 Bucket 權限的 Temporary Security Credential 的 API Endpoint,您可以此 Credential 將檔案上傳至 S3 並取得物件 ETag,接著再以此 ETag 取得該物件的最終 URL,該 URL 即可用於 SPA 系統中。

File Upload Flow

檔案上傳相關的 API Endpoints URL 為 https://tw.buy.yahoo.com/api/fileUploader/

詳細步驟 #

取得 Temporary Security Credential #

首先您需先至 Endpoint GET /api/filerUploader/v1/credentials 取得 Temporary Security Credential。

上傳物件 #

接著依您使用的程式語言至 https://aws.amazon.com/getting-started/tools-sdks/ 取得 AWS 提供的 SDK,搭配上一步取得的 Credential 將物件上傳至 AWS S3。

  • Bucket: ytw-shp-file-uploader
  • Folder: FileUploader/
  • Region: ap-northeast-1
    新版的 AWS SDK 會視情況需要 Region 的參數

在上傳物件的同時,請於 Request Header 加入以下兩個欄位

Header Name Type Value
x-amz-server-side​-encryption String 固定為 AES256
x-amz-meta-YahooWSSID-Authorization String 由 Endpoint GET v1/token 取得的 WSSID
若您使用的是官方的 SDK,請注意指定 custom user-metadata 是否會自動加上前綴 x-amz-meta-,若是,則需注意應只輸入 YahooWSSID-Authorization

成功上傳後,您可由結果取得該物件的 ETag

Java 範例程式
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicSessionCredentials;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.amazonaws.services.s3.model.PutObjectResult;
import org.apache.commons.io.FilenameUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

public class Sample {
    public String uploadAndGetETag() throws Exception {
        // WSSID for authorization, obtained from Endpoint GET v1/token
        // ref: https://tw.supplier.yahoo.com/docs/sp/api/endpoints/common/#get-v1token
        String wssid = "ABCDEFabcdef0123456789._-~";
        // Temporary Security Credential from Endpoint GET /api/filerUploader/v1/credentials
        // ref: https://tw.supplier.yahoo.com/docs/sp/api/file_upload/endpoints/#get-v1credentials
        String credentialId = "ABCDE12345";
        String credentialKey = "ABCDEF/abcdef/123456=";
        String credentialToken = "ABCDEFG/abcdefg/1234567===";

        // Create an S3 client with the provided credentials
        AmazonS3ClientBuilder builder = AmazonS3ClientBuilder.standard();
        builder.withRegion(Regions.AP_NORTHEAST_1);
        builder.withCredentials(new AWSStaticCredentialsProvider(
                new BasicSessionCredentials(
                        credentialId, credentialKey, credentialToken
                )
        ));
        AmazonS3 s3 = builder.build();

        // Prepare metadata for the S3 object
        Map<String, String> userMetadata = new HashMap<>();
        userMetadata.put("YahooWSSID-Authorization", wssid);

        ObjectMetadata metadata = new ObjectMetadata();
        metadata.setSSEAlgorithm(ObjectMetadata.AES_256_SERVER_SIDE_ENCRYPTION);
        metadata.setUserMetadata(userMetadata);

        // Set the content length (optional, but recommended)
        String filePath = "test.png";
        File file = new File(filePath);
        metadata.setContentLength(file.length());

        // Construct the S3 object key and upload the file
        String bucketName = "ytw-shp-file-uploader";
        String key = String.format("FileUploader/%s", FilenameUtils.getName(filePath));
        try (InputStream inputStream = new FileInputStream(file)) {
            PutObjectRequest putObjectRequest = new PutObjectRequest(
                    bucketName, key, inputStream, metadata
            );
            return s3.putObject(putObjectRequest).getETag();
        }
    }
}
PHP 範例程式
<?php

require_once ('vendor/autoload.php');

use Aws\Credentials\CredentialProvider;
use Aws\S3\Exception\S3Exception;
use Aws\S3\S3Client;

// WSSID for authorization, obtained from Endpoint GET v1/token
// ref: https://tw.supplier.yahoo.com/docs/sp/api/endpoints/common/#get-v1token
$wssid = 'ABCDEFabcdef0123456789._-~';

// Temporary Security Credential from Endpoint GET /api/filerUploader/v1/credentials
// ref: https://tw.supplier.yahoo.com/docs/sp/api/file_upload/endpoints/#get-v1credentials
$credentialId = 'ABCDE12345';
$credentialKey = 'ABCDEF/abcdef/123456=';
$credentialToken = 'ABCDEFG/abcdefg/1234567===';

// Create an S3 client with the provided credentials
try
{
    $s3Client = new S3Client
    (
        array
        (
            'region'            => 'ap-northeast-1',
            'version'           => 'latest',
            // ref: https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/guide_credentials_temporary.html
            'credentials'       => array
            (
                'key'           => $credentialId,
                'secret'        => $credentialKey,
                'token'         => $credentialToken,
            )
        )
    );
}
catch (S3Exception $e)
{
    echo "[S3 Client Init Error] " . $e->getMessage() . "\n";
    exit(1);
}

// Construct the S3 object and upload the file
$imgFile = "test.png";
try
{
    // Parameter syntax ref: https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-s3-2006-03-01.html#putobject
    $result = $s3Client->putObject (
        array
        (
            'Bucket'                                => 'ytw-shp-file-uploader',
            'Key'                                   => 'FileUploader/'.basename($imgFile),
            'ServerSideEncryption'                  => 'AES256',
            'SourceFile'                            => $imgFile,
            'x-amz-server-side-encryption'          => 'AES256',
            'x-amz-meta-YahooWSSID-Authorization'   => $wssid,
        )
    );

    echo "ETag: " . $result['ETag'] . "\n";
}
catch (S3Exception $e)
{
    echo "[Upload Error] " . $e->getMessage() . "\n";
    echo "[Detailed Error XML]\n" . $e->getAwsErrorMessage() . "\n";
    echo "Error Code: " . $e->getAwsErrorCode() . "\n";
    echo "Status Code: " . $e->getStatusCode() . "\n";
    exit(2);
}

exit;
?>
Python 範例程式
import boto3

# WSSID for authorization, obtained from Endpoint GET v1/token
# ref: https://tw.supplier.yahoo.com/docs/sp/api/endpoints/common/#get-v1token
wssid = 'ABCDEFabcdef0123456789._-~'

# Temporary Security Credential from Endpoint GET /api/filerUploader/v1/credentials
# ref: https://tw.supplier.yahoo.com/docs/sp/api/file_upload/endpoints/#get-v1credentials
aws_access_key_id = 'ABCDE12345'
aws_secret_access_key = 'ABCDEF/abcdef/123456='
aws_session_token = 'ABCDEFG/abcdefg/1234567==='

# Create an S3 client with the provided credentials
s3 = boto3.client(
    's3',
    region_name='ap-northeast-1',
    aws_access_key_id=aws_access_key_id,
    aws_secret_access_key=aws_secret_access_key,
    aws_session_token=aws_session_token
)

# Construct the S3 object key
file_path = 'test.png'
file_name = file_path.rsplit('/', 1)[-1]
s3_key = 'FileUploader/' + file_name

# Upload the file to S3
bucket_name = 'ytw-shp-file-uploader'
with open(file_path, 'rb') as file:
    response = s3.put_object(
        Bucket=bucket_name,
        Key=s3_key,
        Body=file,
        Metadata={
            'YahooWSSID-Authorization': wssid
        },
        ServerSideEncryption='AES256'
    )
# Get the ETag of the uploaded object
etag = response.get('ETag')
print(f"ETag: {etag}")

取得檔案 URL #

最後,您可以上一步取得的 ETag 詢問 Endpoint GET /api/fileUploader/v1/fileObjects 以取得其 URL,並用於 SPA 系統中。