All Products
Search
Document Center

Object Storage Service:Bagaimana cara membatasi jenis dan ukuran file saat mengunggah objek ke OSS?

Last Updated:Mar 07, 2026

Jika Anda tidak membatasi jenis dan ukuran file yang dapat diunggah ke bucket Object Storage Service (OSS), pengguna mungkin mengunggah objek besar atau berbahaya. Hal ini dapat menyebabkan penggunaan penyimpanan dan bandwidth yang tidak terduga, bahkan dalam beberapa kasus, menyebabkan domain bucket Anda diblokir. OSS tidak menyediakan fitur khusus untuk secara langsung membatasi jenis dan ukuran file saat unggahan. Namun, Anda dapat menetapkan batasan tersebut saat menghasilkan signature di sisi server atau dengan menerapkan logika pembatasan di sisi client.

Hasilkan Post signature dan PostPolicy di sisi server

Untuk skenario yang memerlukan pembatasan atribut file yang diunggah, Anda dapat menghasilkan Post signature, PostPolicy, dan informasi lain yang diperlukan untuk PostObject di sisi server. Client kemudian dapat menggunakan informasi ini untuk mengunggah file secara langsung dengan batasan tertentu, tanpa bergantung pada OSS SDK. Anda dapat menggunakan PostPolicy yang dihasilkan server untuk membatasi file yang diunggah oleh client, misalnya dengan membatasi ukuran atau jenis file. Solusi ini cocok untuk mengunggah file melalui formulir HTML. Perhatikan bahwa solusi ini tidak mendukung unggah multi-bagian (multipart uploads) untuk file besar atau unggah yang dapat dilanjutkan (resumable uploads). Untuk informasi selengkapnya, lihat PostObject.

Kode contoh

Kode contoh sisi server

Kode contoh berikut menunjukkan cara menghasilkan Post signature, Post Policy, dan informasi lain di sisi server:

Catatan

Kode ini mendukung penerapan satu klik. Anda dapat menerapkan kode ini ke Function Compute (FC) dengan satu klik.oss-upload-post-signature-app

Python
import os
from hashlib import sha1 as sha
import json
import base64
import hmac
import datetime
import time

# Konfigurasikan variabel lingkungan OSS_ACCESS_KEY_ID.
access_key_id = os.environ.get('OSS_ACCESS_KEY_ID')
# Konfigurasikan variabel lingkungan OSS_ACCESS_KEY_SECRET.
access_key_secret = os.environ.get('OSS_ACCESS_KEY_SECRET')
# Ganti <YOUR_BUCKET> dengan nama bucket Anda.
bucket = '<YOUR_BUCKET>'
# Format host adalah bucketname.endpoint. Ganti <YOUR_BUCKET> dengan nama bucket Anda. Ganti <YOUR_ENDPOINT> dengan endpoint OSS, seperti oss-cn-hangzhou.aliyuncs.com.
host = 'https://<YOUR_BUCKET>.<YOUR_ENDPOINT>'
# Tentukan awalan untuk file yang akan diunggah ke OSS.
upload_dir = 'user-dir-prefix/'
# Tentukan waktu kedaluwarsa dalam detik.
expire_time = 3600


def generate_expiration(seconds):
    """
    Hasilkan waktu kedaluwarsa dengan menentukan periode validitas dalam detik.
    :param seconds: Periode validitas dalam detik.
    :return: String waktu ISO 8601, seperti "2014-12-01T12:00:00.000Z".
    """
    now = int(time.time())
    expiration_time = now + seconds
    gmt = datetime.datetime.utcfromtimestamp(expiration_time).isoformat()
    gmt += 'Z'
    return gmt


def generate_signature(access_key_secret, expiration, conditions, policy_extra_props=None):
    """
    Hasilkan string signature.
    :param access_key_secret: Rahasia AccessKey dari akun yang memiliki izin untuk mengakses bucket tujuan.
    :param expiration: Waktu kedaluwarsa signature, dalam format ISO 8601 dan UTC. Contoh: "2014-12-01T12:00:00.000Z".
    :param conditions: Kondisi kebijakan yang digunakan untuk membatasi nilai yang diizinkan saat mengunggah formulir.
    :param policy_extra_props: Parameter kebijakan tambahan. Jika parameter baru ditambahkan ke kebijakan, Anda dapat meneruskannya sebagai dictionary.
    :return: signature, string signature.
    """
    policy_dict = {
        'expiration': expiration,
        'conditions': conditions
    }
    if policy_extra_props is not None:
        policy_dict.update(policy_extra_props)
    policy = json.dumps(policy_dict).strip()
    policy_encode = base64.b64encode(policy.encode())
    h = hmac.new(access_key_secret.encode(), policy_encode, sha)
    sign_result = base64.b64encode(h.digest()).strip()
    return sign_result.decode()

def generate_upload_params():
    policy = {
        # Periode validitas.
        "expiration": generate_expiration(expire_time),
        # Batasan.
        "conditions": [
            # Kode status yang dikembalikan setelah unggahan berhasil jika success_action_redirect tidak ditentukan. Nilai default adalah 204.
            ["eq", "$success_action_status", "200"],
            # Nilai field formulir harus dimulai dengan awalan yang ditentukan. Misalnya, untuk menentukan bahwa nilai key harus dimulai dengan user/user1, Anda dapat menulis ["starts-with", "$key", "user/user1"].
            ["starts-with", "$key", upload_dir],
            # Batasi ukuran minimum dan maksimum objek yang diunggah dalam byte.
            ["content-length-range", 1, 1000000],
            # Batasi file yang diunggah hanya ke jenis gambar tertentu.
            ["in", "$content-type", ["image/jpg", "image/png"]]
        ]
    }
    signature = generate_signature(access_key_secret, policy.get('expiration'), policy.get('conditions'))
    response = {
        'policy': base64.b64encode(json.dumps(policy).encode('utf-8')).decode(),
        'ossAccessKeyId': access_key_id,
        'signature': signature,
        'host': host,
        'dir': upload_dir
        # Anda dapat menambahkan parameter lain di sini.
    }
    return json.dumps(response)
Java
package com.aliyun.sample;

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.codehaus.jettison.json.JSONObject;
import java.util.Date;

@Controller
public class PostSignatureController {
    @Autowired
    private OSS ossClient;

    @Autowired
    private OssConfig ossConfig;

    @GetMapping("/get_post_signature_for_oss_upload")
    @ResponseBody
    public String generatePostSignature() {
        JSONObject response = new JSONObject();
        try {
            long expireEndTime = System.currentTimeMillis() + ossConfig.getExpireTime() * 1000;
            Date expiration = new Date(expireEndTime);
            PolicyConditions policyConds = new PolicyConditions();
            policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
            policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, ossConfig.getDir());
            String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
            byte[] binaryData = postPolicy.getBytes("utf-8");
            String encodedPolicy = BinaryUtil.toBase64String(binaryData);
            String postSignature = ossClient.calculatePostSignature(postPolicy);
            response.put("ossAccessKeyId", ossConfig.getAccessKeyId());
            response.put("policy", encodedPolicy);
            response.put("signature", postSignature);
            response.put("dir", ossConfig.getDir());
            response.put("host", ossConfig.getHost());
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("HTTP Status Code: " + oe.getRawResponseError());
            System.out.println("Error Message: " + oe.getErrorMessage());
            System.out.println("Error Code:       " + oe.getErrorCode());
            System.out.println("Request ID:      " + oe.getRequestId());
            System.out.println("Host ID:           " + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message: " + ce.getMessage());
        } catch (Exception e) {
            System.out.println("Caught an unexpected exception: " + e.getMessage());
        }
        return response.toString();
    }
}
Go
package main

import (
	"crypto/hmac"
	"crypto/sha1"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"os"
	"time"
)

var (
	// Konfigurasikan variabel lingkungan OSS_ACCESS_KEY_ID.
	accessKeyId = os.Getenv("OSS_ACCESS_KEY_ID")
	// Konfigurasikan variabel lingkungan OSS_ACCESS_KEY_SECRET.
	accessKeySecret = os.Getenv("OSS_ACCESS_KEY_SECRET")
	// Format host adalah bucketname.endpoint. Ganti ${your-bucket} dengan nama bucket Anda. Ganti ${your-endpoint} dengan endpoint OSS, seperti oss-cn-hangzhou.aliyuncs.com.
	host = "http://${your-bucket}.${your-endpoint}"
	// Tentukan awalan untuk file yang akan diunggah ke OSS.
	uploadDir = "user-dir-prefix/"
	// Tentukan waktu kedaluwarsa dalam detik.
	expireTime = int64(3600)
)

type ConfigStruct struct {
	Expiration string          `json:"expiration"`
	Conditions [][]interface{} `json:"conditions"`
}

type PolicyToken struct {
	AccessKeyId string `json:"ossAccessKeyId"`
	Host        string `json:"host"`
	Signature   string `json:"signature"`
	Policy      string `json:"policy"`
	Directory   string `json:"dir"`
}

func getGMTISO8601(expireEnd int64) string {
	return time.Unix(expireEnd, 0).UTC().Format("2006-01-02T15:04:05Z")
}

func getPolicyToken() string {
	now := time.Now().Unix()
	expireEnd := now + expireTime
	tokenExpire := getGMTISO8601(expireEnd)

	var config ConfigStruct
	config.Expiration = tokenExpire

	// Tambahkan pembatasan awalan file.
	config.Conditions = append(config.Conditions, []interface{}{"starts-with", "$key", uploadDir})

	// Tambahkan pembatasan ukuran file, misalnya dari 1 KB hingga 10 MB.
	minSize := int64(1024)
	maxSize := int64(10 * 1024 * 1024)
	config.Conditions = append(config.Conditions, []interface{}{"content-length-range", minSize, maxSize})

	result, err := json.Marshal(config)
	if err != nil {
		fmt.Println("callback json err:", err)
		return ""
	}

	encodedResult := base64.StdEncoding.EncodeToString(result)
	h := hmac.New(sha1.New, []byte(accessKeySecret))
	io.WriteString(h, encodedResult)
	signedStr := base64.StdEncoding.EncodeToString(h.Sum(nil))

	policyToken := PolicyToken{
		AccessKeyId: accessKeyId,
		Host:        host,
		Signature:   signedStr,
		Policy:      encodedResult,
		Directory:   uploadDir,
	}

	response, err := json.Marshal(policyToken)
	if err != nil {
		fmt.Println("json err:", err)
		return ""
	}

	return string(response)
}

func handler(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path == "/" {
		http.ServeFile(w, r, "templates/index.html")
		return
	} else if r.URL.Path == "/get_post_signature_for_oss_upload" {
		policyToken := getPolicyToken()
		w.Header().Set("Content-Type", "application/json")
		w.Write([]byte(policyToken))
		return
	}
	http.NotFound(w, r)
}

func main() {
	http.HandleFunc("/", handler)
	http.ListenAndServe(":8080", nil)
}
PHP
<?php
function gmt_iso8601($time)
{
    return str_replace('+00:00', '.000Z', gmdate('c', $time));
}

// Dapatkan kredensial akses dari variabel lingkungan. Sebelum menjalankan kode contoh ini, pastikan variabel lingkungan ALIBABA_CLOUD_ACCESS_KEY_ID dan ALIBABA_CLOUD_ACCESS_KEY_SECRET telah dikonfigurasi.
$accessKeyId = getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
$accessKeySecret = getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
// Format $host adalah '<YOUR-BUCKET>.<YOUR-ENDPOINT>'. Ganti variabel dengan informasi aktual Anda.
$host = 'http://<YOUR-BUCKET>.<YOUR-ENDPOINT>';
// Awalan yang ditentukan pengguna saat mengunggah file.
$dir = 'user-dir-prefix/';          

$now = time();
// Atur kebijakan untuk kedaluwarsa dalam 10 detik. Setelah periode ini, kebijakan menjadi tidak valid.
$expire = 30;  
$end = $now + $expire;
$expiration = gmt_iso8601($end);

// Ukuran file maksimum. Anda dapat mengaturnya sendiri.
$condition = array(0 => 'content-length-range', 1 => 0, 2 => 1048576000);
$conditions[] = $condition;

// Data yang diunggah harus dimulai dengan $dir, jika tidak unggahan akan gagal. Langkah ini tidak wajib tetapi direkomendasikan demi keamanan untuk mencegah pengguna mengunggah ke direktori lain melalui kebijakan.
$start = array(0 => 'starts-with', 1 => '$key', 2 => $dir);
$conditions[] = $start;


$arr = array('expiration' => $expiration, 'conditions' => $conditions);
$policy = json_encode($arr);
$base64_policy = base64_encode($policy);
$string_to_sign = $base64_policy;
$signature = base64_encode(hash_hmac('sha1', $string_to_sign, $accessKeySecret, true));

$response = array();
$response['ossAccessKeyId'] = $accessKeyId;
$response['host'] = $host;
$response['policy'] = $base64_policy;
$response['signature'] = $signature;
$response['dir'] = $dir;  
echo json_encode($response);
Node.js
const express = require("express");
const { Buffer } = require("buffer");
const OSS = require("ali-oss");
const app = express();
const path = require("path");
const config = {
  // Konfigurasikan variabel lingkungan ALIBABA_CLOUD_ACCESS_KEY_ID.
  accessKeyId: process.env.ALIBABA_CLOUD_ACCESS_KEY_ID,
  // Konfigurasikan variabel lingkungan ALIBABA_CLOUD_ACCESS_KEY_SECRET.
  accessKeySecret: process.env.ALIBABA_CLOUD_ACCESS_KEY_SECRET,
  // Ganti <YOUR-BUCKET> dengan nama bucket Anda.
  bucket: "<YOUR-BUCKET>",
  // Tentukan awalan untuk file yang akan diunggah ke OSS.
  dir: "prefix/",
};

app.use(express.static(path.join(__dirname, "templates")));

app.get("/get_post_signature_for_oss_upload", async (req, res) => {
  const client = new OSS(config);
  const date = new Date();
  // Atur periode validitas signature dalam detik.
  date.setSeconds(date.getSeconds() + 3600);
  const policy = {
    expiration: date.toISOString(),
    conditions: [
      // Atur batas ukuran untuk file yang diunggah.
      ["content-length-range", 0, 1048576000],
      // Batasi bucket tempat file dapat diunggah.
      { bucket: client.options.bucket },
    ],
  };
  const formData = await client.calculatePostSignature(policy);
  const host = `http://${config.bucket}.${
    (await client.getBucketLocation()).location
  }.aliyuncs.com`.toString();
  const params = {
    policy: formData.policy,
    signature: formData.Signature,
    ossAccessKeyId: formData.OSSAccessKeyId,
    host,
    dir: config.dir,
  };
  res.json(params);
});

app.get(/^(.+)*\.(html|js)$/i, async (req, res) => {
  res.sendFile(path.join(__dirname, "./templates", req.originalUrl));
});

app.listen(8000, () => {
  console.log("http://127.0.0.1:8000");
});
Ruby
require 'sinatra'
require 'base64'
require 'open-uri'
require 'cgi'
require 'openssl'
require 'json'
require 'sinatra/reloader'
require 'sinatra/content_for'

# Atur path folder publik ke folder templates di direktori saat ini.
set :public_folder, File.dirname(__FILE__) + '/templates'

# Konfigurasikan variabel lingkungan ALIBABA_CLOUD_ACCESS_KEY_ID.
$access_key_id = ENV['ALIBABA_CLOUD_ACCESS_ID']
# Konfigurasikan variabel lingkungan ALIBABA_CLOUD_ACCESS_KEY_SECRET.
$access_key_secret = ENV['ALIBABA_CLOUD_ACCESS_SECRET']

# Format $host adalah <bucketname>.<endpoint>. Ganti <bucketname> dan <endpoint> dengan informasi aktual Anda.
$host = 'http://<bucketname>.<endpoint>';

# Awalan untuk file yang diunggah pengguna.
$upload_dir = 'user-dir-prefix/'
# Waktu kedaluwarsa dalam detik.
$expire_time = 30
$server_ip = "0.0.0.0"
$server_port = 8000

if ARGV.length == 1 
  $server_port = ARGV[0]
elsif ARGV.length == 2
  $server_ip = ARGV[0]
  $server_port = ARGV[1]
end

puts "App server is running on: http://#{$server_ip}:#{$server_port}"

def hash_to_jason(source_hash)
  jason_string = source_hash.to_json;    

  jason_string.gsub!("\":[", "\": [")
  jason_string.gsub!("\",\"", "\", \"")
  jason_string.gsub!("],\"", "], \"")
  jason_string.gsub!("\":\"", "\": \"")

  jason_string
end


def get_token()
  expire_syncpoint = Time.now.to_i + $expire_time
  expire = Time.at(expire_syncpoint).utc.iso8601()
  response.headers['expire'] = expire
  policy_dict = {}
  condition_arrary = Array.new
  array_item = Array.new
  array_item.push('starts-with')
  array_item.push('$key')
  array_item.push($upload_dir)
  condition_arrary.push(array_item)
  policy_dict["conditions"] = condition_arrary
  policy_dict["expiration"] = expire
  policy = hash_to_jason(policy_dict)
  policy_encode = Base64.strict_encode64(policy).chomp;
  h = OpenSSL::HMAC.digest('sha1', $access_key_secret, policy_encode)
  hs = Digest::MD5.hexdigest(h)
  sign_result = Base64.strict_encode64(h).strip()
  token_dict = {}
  token_dict['ossAccessKeyId'] = $access_key_id
  token_dict['host'] = $host
  token_dict['policy'] = policy_encode
  token_dict['signature'] = sign_result 
  token_dict['expire'] = expire_syncpoint
  token_dict['dir'] = $upload_dir
  result = hash_to_jason(token_dict)
  result
end

set :bind, $server_ip
set :port, $server_port

get '/get_post_signature_for_oss_upload' do
  token = get_token()
  puts "Token: #{token}"
  token
end

get '/*' do
  puts "********************* GET "
  send_file File.join(settings.public_folder, 'index.html')
end

end

if ARGV.length == 1 
  $server_port = ARGV[0]
elsif ARGV.length == 2
  $server_ip = ARGV[0]
  $server_port = ARGV[1]
end

$server_ip = "0.0.0.0"
$server_port = 8000

puts "App server is running on: http://#{$server_ip}:#{$server_port}"

set :bind, $server_ip
set :port, $server_port

get '/get_sts_token_for_oss_upload' do
  token = get_sts_token_for_oss_upload()
  response = {
    "AccessKeyId" => token["Credentials"]["AccessKeyId"],
    "AccessKeySecret" => token["Credentials"]["AccessKeySecret"],
    "SecurityToken" => token["Credentials"]["SecurityToken"]
  }
  response.to_json
end

get '/*' do
  puts "********************* GET "
  send_file File.join(settings.public_folder, 'index.html')
end
C#
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Http;
using System.IO;
using System.Collections.Generic;
using System;
using System.Globalization;
using System.Text;
using System.Security.Cryptography;
using Newtonsoft.Json;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;

namespace YourNamespace
{
    public class Program
    {
        private ILogger<Program> _logger;
        // Konfigurasikan variabel lingkungan ALIBABA_CLOUD_ACCESS_KEY_ID.
        public string AccessKeyId { get; set; } = Environment.GetEnvironmentVariable("ALIBABA_CLOUD_ACCESS_KEY_ID");
        // Konfigurasikan variabel lingkungan ALIBABA_CLOUD_ACCESS_KEY_SECRET.
        public string AccessKeySecret { get; set; } = Environment.GetEnvironmentVariable("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
        // Format host adalah bucketname.endpoint. Ganti <YOUR-BUCKET> dengan nama bucket Anda. Ganti <YOUR-ENDPOINT> dengan endpoint OSS, seperti oss-cn-hangzhou.aliyuncs.com.
        public string Host { get; set; } = "<YOUR-BUCKET>.<YOUR-ENDPOINT>";
        // Tentukan awalan untuk file yang akan diunggah ke OSS.
        public string UploadDir { get; set; } = "user-dir-prefix/";
        // Tentukan waktu kedaluwarsa dalam detik.
        public int ExpireTime { get; set; } = 3600;
        public class PolicyConfig
        {
            public string expiration { get; set; }
            public List<List<object>> conditions { get; set; }
        }
        public class PolicyToken
        {
            public string Accessid { get; set; }
            public string Policy { get; set; }
            public string Signature { get; set; }
            public string Dir { get; set; }
            public string Host { get; set; }
            public string Expire { get; set; }
        }
        public static void Main(string[] args)
        {
            var builder = WebApplication.CreateBuilder(args);
            var app = builder.Build();

            builder.Logging.AddConsole();
            var logger = builder.Services.BuildServiceProvider().GetRequiredService<ILogger<Program>>();

            app.UseStaticFiles(); 

            app.MapGet("/", async (context) =>
            {
                var filePath = Path.Combine(Directory.GetCurrentDirectory(), "templates/index.html");
                var htmlContent = await File.ReadAllTextAsync(filePath);
                await context.Response.WriteAsync(htmlContent);
                logger.LogInformation("GET request to root path");
            });

            app.MapGet("/get_post_signature_for_oss_upload", async (context) =>
            {
                var program = new Program(logger);
                var token = program.GetPolicyToken();

                logger.LogInformation($"Token: {token}");

                context.Response.ContentType = "application/json";
                await context.Response.WriteAsync(token);
            });

            app.Run();
        }

        public Program(ILogger<Program> logger)
        {
            _logger = logger;
        }

        private string ToUnixTime(DateTime dateTime)
        {
            return ((DateTimeOffset)dateTime).ToUnixTimeSeconds().ToString();
        }

        private string GetPolicyToken()
        {
            var expireDateTime = DateTime.Now.AddSeconds(ExpireTime);
            var config = new PolicyConfig
            {
                expiration = FormatIso8601Date(expireDateTime),
                conditions = new List<List<object>>()
            };
            config.conditions.Add(new List<object>
            {
                "content-length-range", 0, 1048576000
            });
            var policy = JsonConvert.SerializeObject(config);
            var policyBase64 = EncodeBase64("utf-8", policy);
            var signature = ComputeSignature(AccessKeySecret, policyBase64);
            var policyToken = new PolicyToken
            {
                Accessid = AccessKeyId,
                Host = Host,
                Policy = policyBase64,
                Signature = signature,
                Expire = ToUnixTime(expireDateTime),
                Dir = UploadDir
            };
            return JsonConvert.SerializeObject(policyToken);
        }

        private string FormatIso8601Date(DateTime dtime)
        {
            return dtime.ToUniversalTime().ToString("yyyy-MM-dd'T'HH:mm:ss.fff'Z'",
                                    CultureInfo.CurrentCulture);
        }

        private string EncodeBase64(string codeType, string code)
        {
            string encode = "";
            byte[] bytes = Encoding.GetEncoding(codeType).GetBytes(code);
            try
            {
                encode = Convert.ToBase64String(bytes);
            }
            catch
            {
                encode = code;
            }
            return encode;
        }

        private string ComputeSignature(string key, string data)
        {
            using (var algorithm = new HMACSHA1(Encoding.UTF8.GetBytes(key)))
            {
                return Convert.ToBase64String(algorithm.ComputeHash(Encoding.UTF8.GetBytes(data)));
            }
        }
    }
}

Kode contoh sisi client

Kode contoh berikut menunjukkan cara client web menggunakan Post signature, Post Policy, dan informasi lain untuk mengunggah file ke OSS:

const form = document.querySelector("form");
const fileInput = document.querySelector("#file");
form.addEventListener("submit", (event) => {
  event.preventDefault();
  const file = fileInput.files[0];
  if (!fileInput.files[0]) {
    alert('Please select a file to upload.');
    return;
  }
  const filename = fileInput.files[0].name;
  fetch("/get_post_signature_for_oss_upload", { method: "GET" })
    .then((response) => {
      if (!response.ok) {
        throw new Error("Failed to obtain the signature.");
      }
      return response.json();
    })
    .then((data) => {
      const formData = new FormData();
      formData.append("name", filename);
      formData.append("policy", data.policy);
      formData.append("OSSAccessKeyId", data.ossAccessKeyId);
      formData.append("success_action_status", "200");
      formData.append("signature", data.signature);
      formData.append("key", data.dir + filename);
      formData.append("file", file);

      return fetch(data.host, { method: "POST", body: formData });
    })
    .then((response) => {
      if (response.ok) {
        console.log("Upload successful");
        alert("File uploaded.");
      } else {
        console.log("Upload failed", response);
        alert("Upload failed. Please try again later.");
      }
    })
    .catch((error) => {
      console.error("An error occurred:", error);
    });
});

Hasilkan URL yang ditandatangani di sisi server

Field content-length-range tidak didukung untuk penandatanganan URL. Oleh karena itu, Anda tidak dapat menggunakan metode ini untuk membatasi ukuran file yang diunggah. Jika ingin membatasi unggahan hanya ke jenis file tertentu, Anda dapat menentukan header content-type saat mengonfigurasi server untuk menghasilkan URL yang ditandatangani. Saat client menggunakan URL tersebut untuk mengunggah file, file harus sesuai dengan salah satu format yang ditentukan. Untuk informasi selengkapnya, lihat Add signatures to URLs.

Kode contoh

Kode contoh sisi server

Kode contoh berikut menunjukkan cara menghasilkan URL yang ditandatangani di sisi server:

Catatan

Kode ini mendukung penerapan satu klik. Anda dapat menerapkan kode ini ke Function Compute (FC) dengan satu klik.oss-upload-presigned-url-app

Python
import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider

# Dapatkan kredensial akses dari variabel lingkungan. Sebelum menjalankan kode contoh ini, pastikan variabel lingkungan OSS_ACCESS_KEY_ID dan OSS_ACCESS_KEY_SECRET telah dikonfigurasi.
auth = oss2.ProviderAuth(EnvironmentVariableCredentialsProvider())
# Ganti <YOUR_ENDPOINT> dengan endpoint wilayah tempat bucket Anda berada. Misalnya, jika bucket Anda berada di wilayah China (Hangzhou), atur endpoint ke https://oss-cn-hangzhou.aliyuncs.com.
# Ganti <YOUR_BUCKET> dengan nama bucket Anda.
bucket = oss2.Bucket(auth, '<YOUR_ENDPOINT>', '<YOUR_BUCKET>')
# Tentukan waktu kedaluwarsa dalam detik.
expire_time = 3600
# Tentukan path lengkap objek, misalnya exampledir/exampleobject.png. Path lengkap tidak boleh mengandung nama bucket.
object_name = 'exampledir/exampleobject.png'

def generate_presigned_url():
    # Tentukan header.
    headers = dict()
    # Tentukan Content-Type.
    headers['Content-Type'] = 'image/png'
    # Tentukan kelas penyimpanan.
    # headers["x-oss-storage-class"] = "Standard"
    # Saat menghasilkan URL yang ditandatangani, OSS secara default melakukan escape karakter garis miring (/) dalam path lengkap objek. Hal ini membuat URL yang dihasilkan tidak dapat digunakan.
    # Atur slash_safe ke True. OSS tidak akan melakukan escape karakter garis miring (/) dalam path lengkap objek. URL yang dihasilkan kemudian dapat digunakan secara langsung.
    url = bucket.sign_url('PUT', object_name, expire_time, slash_safe=True, headers=headers)
    return url
Java
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Bean;
import com.aliyun.oss.HttpMethod;
import com.aliyun.oss.model.GeneratePresignedUrlRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.net.URL;
import java.util.Date;
import javax.annotation.PreDestroy;

@Configuration
public class OssConfig {

    /**
     * Ganti <your-endpoint> dengan endpoint OSS, misalnya oss-cn-hangzhou.aliyuncs.com.
     */
    private static final String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";

    /**
     * Atur accessKeyId menggunakan variabel lingkungan ALIBABA_CLOUD_ACCESS_KEY_ID.
     */
    @Value("${ALIBABA_CLOUD_ACCESS_KEY_ID}")
    private String accessKeyId;

    /**
     * Atur accessKeySecret menggunakan variabel lingkungan ALIBABA_CLOUD_ACCESS_KEY_SECRET.
     */
    @Value("${ALIBABA_CLOUD_ACCESS_KEY_SECRET}")
    private String accessKeySecret;

    private OSS ossClient;


    @Bean
    public OSS getSssClient() {
        ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        return ossClient;
    }

    @PreDestroy
    public void onDestroy() {
        ossClient.shutdown();
    }
}

@Controller
public class PresignedURLController {

    /**
     * Ganti <your-bucket> dengan nama bucket Anda.
     * Tentukan awalan untuk file yang akan diunggah ke OSS.
     * Ganti <your-object> dengan path lengkap objek, misalnya exampleobject.txt. Path lengkap tidak boleh mengandung nama bucket.
     * Tentukan waktu kedaluwarsa dalam milidetik.
     */
    private static final String BUCKET_NAME = "<your-bucket>";
    private static final String OBJECT_NAME = "<your-object>";
    private static final long EXPIRE_TIME = 3600 * 1000L;

    @Autowired
    private OSS ossClient;

    @GetMapping("/get_presigned_url_for_oss_upload")
    @ResponseBody
    public String generatePresignedURL() {

        try {
            GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(BUCKET_NAME, OBJECT_NAME, HttpMethod.PUT);
            Date expiration = new Date(System.currentTimeMillis() + EXPIRE_TIME);
            request.setExpiration(expiration);
            request.setContentType("image/png");
            URL signedUrl = ossClient.generatePresignedUrl(request);
            return signedUrl.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
Go
package main

import (
	"fmt"
	"net/http"
	"os"

	"github.com/aliyun/aliyun-oss-go-sdk/oss"
)

func getURL() string {
	// Atur yourEndpoint ke endpoint bucket Anda. Misalnya, jika bucket Anda berada di wilayah China (Hangzhou), atur endpoint ke https://oss-cn-hangzhou.aliyuncs.com. Untuk wilayah lain, atur endpoint sesuai.
	endpoint := "https://oss-cn-beijing.aliyuncs.com"
	// Tentukan nama bucket, misalnya examplebucket.
	bucketName := "examplebucket"
	// Tentukan path lengkap file, misalnya exampledir/exampleobject.txt. Path lengkap tidak boleh mengandung nama bucket.
	objectName := "exampledir/exampleobject.txt"
	// Dapatkan kredensial akses dari variabel lingkungan. Sebelum menjalankan kode contoh ini, pastikan variabel lingkungan ALIBABA_CLOUD_ACCESS_KEY_ID dan ALIBABA_CLOUD_ACCESS_KEY_SECRET telah dikonfigurasi.
	accessKeyID := os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_ID")
	accessKeySecret := os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET")

	client, err := oss.New(endpoint, accessKeyID, accessKeySecret)
	if err != nil {
		fmt.Println("json err:", err)
	}
	bucket, err := client.Bucket(bucketName)
	if err != nil {
		fmt.Println("json err:", err)
	}
	options := []oss.Option{
		oss.ContentType("image/png"),
	}
	signedURL, err := bucket.SignURL(objectName, oss.HTTPPut, 60, options...)
	if err != nil {
		fmt.Println("json err:", err)
	}

	return signedURL
}

func handler(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path == "/" {
		http.ServeFile(w, r, "templates/index.html")
		return
	} else if r.URL.Path == "/get_presigned_url_for_oss_upload" {
		url := getURL()
		fmt.Fprintf(w, "%s", url)
		return
	}
	http.NotFound(w, r)
}
func main() {
	http.HandleFunc("/", handler)
	http.ListenAndServe(":8080", nil)
}
PHP
<?php
require_once __DIR__ . '/vendor/autoload.php';
use OSS\OssClient;
use OSS\Core\OssException;
use OSS\Http\RequestCore;
use OSS\Http\ResponseCore;
// Sebelum menjalankan kode contoh ini, pastikan variabel lingkungan ALIBABA_CLOUD_ACCESS_KEY_ID dan ALIBABA_CLOUD_ACCESS_KEY_SECRET telah dikonfigurasi.
$accessKeyId = getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
$accessKeySecret = getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
// Atur yourEndpoint ke endpoint wilayah tempat bucket Anda berada. Misalnya, jika bucket Anda berada di wilayah China (Hangzhou), atur endpoint ke https://oss-cn-hangzhou.aliyuncs.com.
$endpoint = "<YOUR-ENDPOINT>";
// Tentukan nama bucket.
$bucket= "<YOUR-BUCKET>";
// Tentukan path lengkap objek, tidak termasuk nama bucket.
$object = "test.png";
// Atur periode validitas URL yang ditandatangani menjadi 3600 detik.
$timeout = 3600;
try {
    $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, false);
    // Hasilkan URL yang ditandatangani.
    $signedUrl = $ossClient->signUrl($bucket, $object, $timeout, "PUT", array('Content-Type' => 'image/png'));
    // Cetak data yang dikembalikan.
    echo $signedUrl;
} catch (OssException $e) {
    printf($e->getMessage() . "\n");
    return;
}
Node.js
const express = require("express");
const { Buffer } = require("buffer");
const OSS = require("ali-oss");
const app = express();
const path = require("path");
const fs = require("fs");
const axios = require("axios");

const config = {
  // Atur <YOURREGION> ke wilayah tempat bucket Anda berada. Misalnya, jika bucket Anda berada di wilayah China (Hangzhou), atur region ke oss-cn-hangzhou.
  region: '<YOURREGION>',
  // Konfigurasikan variabel lingkungan ALIBABA_CLOUD_ACCESS_KEY_ID.
  accessKeyId: process.env.ALIBABA_CLOUD_ACCESS_KEY_ID,
  // Konfigurasikan variabel lingkungan ALIBABA_CLOUD_ACCESS_KEY_SECRET.
  accessKeySecret: process.env.ALIBABA_CLOUD_ACCESS_KEY_SECRET,
  // Ganti <YOUR-BUCKET> dengan nama bucket Anda.
  bucket: "<YOUR-BUCKET>",
}
const object = "examplefile.png";

app.use(express.static(path.join(__dirname, "templates")));

app.get("/get_presigned_url_for_oss_upload", async (req, res) => {
    const client = new OSS(config);
    const url = client.signatureUrl(object, {
        method: "PUT",
        "Content-Type": "application/x-www-form-urlencoded",
    });
    res.send(url); 
    console.log(url);
  });

app.listen(8000, () => {
  console.log("http://127.0.0.1:8000");
});
Ruby
require 'sinatra'
require 'base64'
require 'open-uri'
require 'cgi'
require 'openssl'
require 'json'
require 'sinatra/reloader'
require 'sinatra/content_for'
require 'aliyun/oss'
include Aliyun::OSS

# Atur jalur folder publik ke folder templat di direktori saat ini.
set :public_folder, File.dirname(__FILE__) + '/templates'

# Konfigurasikan variabel lingkungan ALIBABA_CLOUD_ACCESS_KEY_ID.
$access_key_id = ENV['ALIBABA_CLOUD_ACCESS_KEY_ID']
# Konfigurasikan variabel lingkungan ALIBABA_CLOUD_ACCESS_KEY_SECRET.
$access_key_secret = ENV['ALIBABA_CLOUD_ACCESS_KEY_SECRET']

# Tentukan jalur lengkap objek, misalnya exampledir/exampleobject.png. Jalur lengkap tidak boleh berisi nama bucket.
object_key = 'exampledir/exampleobject.png'

def get_presigned_url(client, object_key)
  # Ganti <YOUR-BUCKET> dengan nama bucket Anda.
  bucket = client.get_bucket('<YOUR-BUCKET>')
  # Hasilkan URL yang ditandatangani dan tentukan masa berlakunya selama 1 jam (3600 detik).
  bucket.object_url(object_key, 3600)
end

client = Aliyun::OSS::Client.new(
  # Ganti <YOUR-ENDPOINT> dengan titik akhir wilayah tempat bucket Anda berada. Misalnya, jika bucket Anda berada di wilayah Tiongkok (Hangzhou), atur titik akhir menjadi https://oss-cn-hangzhou.aliyuncs.com.
  endpoint: '<YOUR-ENDPOINT>',
  # Dapatkan kredensial akses dari variabel lingkungan. Sebelum menjalankan contoh kode ini, pastikan variabel lingkungan OSS_ACCESS_KEY_ID dan OSS_ACCESS_KEY_SECRET telah dikonfigurasi.
  access_key_id: $access_key_id,
  access_key_secret: $access_key_secret
)


if ARGV.length == 1 
  $server_port = ARGV[0]
elsif ARGV.length == 2
  $server_ip = ARGV[0]
  $server_port = ARGV[1]
end

$server_ip = "0.0.0.0"
$server_port = 8000

puts "Server aplikasi sedang berjalan di: http://#{$server_ip}:#{$server_port}"

set :bind, $server_ip
set :port, $server_port

get '/get_presigned_url_for_oss_upload' do
  url = get_presigned_url(client, object_key.to_s)
  puts "Token: #{url}"
  url
end

get '/*' do
  puts "********************* GET "
  send_file File.join(settings.public_folder, 'index.html')
end
C#
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Http;
using System.IO;
using System;
using Microsoft.Extensions.Logging;
using Aliyun.OSS;

namespace YourNamespace
{
    public class Program
    {
        private ILogger<Program> _logger;

        // Konfigurasikan variabel lingkungan ALIBABA_CLOUD_ACCESS_KEY_ID.
        public string AccessKeyId { get; set; } = Environment.GetEnvironmentVariable("ALIBABA_CLOUD_ACCESS_KEY_ID");
        // Konfigurasikan variabel lingkungan ALIBABA_CLOUD_ACCESS_KEY_SECRET.
        public string AccessKeySecret { get; set; } = Environment.GetEnvironmentVariable("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
        // Ganti <YOUR-ENDPOINT> dengan endpoint wilayah tempat bucket Anda berada. Misalnya, jika bucket Anda berada di wilayah China (Hangzhou), atur endpoint ke https://oss-cn-hangzhou.aliyuncs.com.
        private string EndPoint { get; set; } = "<YOUR-ENDPOINT>";
        // Ganti <YOUR-BUCKET> dengan nama bucket Anda.
        private string BucketName { get; set; } = "<YOUR-BUCKET>";
        private string ObjectName { get; set; } = "exampledir/exampleobject2.png";

        public static void Main(string[] args)
        {
            var builder = WebApplication.CreateBuilder(args);
            var app = builder.Build();

            // Tambahkan logging.
            builder.Logging.AddConsole();
            var logger = builder.Services.BuildServiceProvider().GetRequiredService<ILogger<Program>>();

            app.UseStaticFiles(); // Tambahkan baris ini untuk mengaktifkan middleware file statis.

            app.MapGet("/", async (context) =>
            {
                var filePath = Path.Combine(Directory.GetCurrentDirectory(), "templates/index.html");
                var htmlContent = await File.ReadAllTextAsync(filePath);
                await context.Response.WriteAsync(htmlContent);

                // Cetak log.
                logger.LogInformation("GET request to root path");
            });

            app.MapGet("/get_presigned_url_for_oss_upload", async (context) =>
            {
                var program = new Program(logger);
                var signedUrl = program.GetSignedUrl();

                logger.LogInformation($"SignedUrl: {signedUrl}"); // Cetak nilai token.
                await context.Response.WriteAsync(signedUrl);
            });

            app.Run();
        }

        // Konstruktor untuk injeksi ILogger.
        public Program(ILogger<Program> logger)
        {
            _logger = logger;
        }

        private string GetSignedUrl()
        {
            // Buat instance OSSClient.
            var ossClient = new OssClient(EndPoint, AccessKeyId, AccessKeySecret);

            // Hasilkan URL yang ditandatangani.
            var generatePresignedUriRequest = new GeneratePresignedUriRequest(BucketName, ObjectName, SignHttpMethod.Put)
            {
                Expiration = DateTime.Now.AddHours(1),
                ContentType = "image/png"
            };
            var signedUrl = ossClient.GeneratePresignedUri(generatePresignedUriRequest);

            return signedUrl.ToString();
        }
    }
}

Kode contoh sisi client

Kode contoh berikut menunjukkan cara client web menggunakan URL yang ditandatangani untuk mengunggah file ke OSS:

const form = document.querySelector("form");
form.addEventListener("submit", (event) => {
  event.preventDefault();
  const fileInput = document.querySelector("#file");
  const file = fileInput.files[0];
  fetch("/get_presigned_url_for_oss_upload", { method: "GET" })
    .then((response) => {
      if (!response.ok) {
        throw new Error("Failed to obtain the presigned URL.");
      }
      return response.text();
    })
    .then((url) => {
      fetch(url, {
        method: "PUT",
        headers: new Headers({
          "Content-Type": "image/png",
        }),
        body: file,
      }).then((response) => {
        if (!response.ok) {
          throw new Error("Failed to upload the file to OSS.");
        }
        console.log(response);
        alert("File uploaded.");
      });
    })
    .catch((error) => {
      console.error("An error occurred:", error);
      alert(error.message);
    });
});

Intersepsi sisi client

Anda dapat menggunakan kode JavaScript di sisi client untuk membatasi properti file yang diunggah. Gunakan pernyataan kondisional untuk memeriksa apakah file memenuhi persyaratan ukuran dan jenis. Jika tidak, cegah unggahan dan tampilkan peringatan atau pesan kesalahan. Perhatikan bahwa pembatasan sisi client tidak berlaku untuk unggahan yang menggunakan kredensial akses temporary dari Security Token Service (STS). Jika kredensial akses temporary tersebut bocor, pengguna berbahaya dapat melewati pembatasan sisi client dan mengunggah file berbahaya ke bucket OSS Anda.

Kode contoh

Kode contoh sisi client

Kode contoh berikut menunjukkan cara menggunakan atribut files dan accept dari elemen <input type="file"> untuk memeriksa apakah ukuran dan jenis file memenuhi persyaratan:

<!DOCTYPE html>
<html>
<head>
  <title>File Upload</title>
  <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
</head>
<body>
  <input type="file" id="file-upload" accept="image/jpeg, image/png, application/pdf" />
  <button onclick="uploadFile()">Upload</button>

  <script>
    function uploadFile() {
      const fileInput = document.getElementById('file-upload');
      const file = fileInput.files[0];

      // Batas ukuran file dalam byte.
      const maxFileSize = 1024 * 1024; // 1 MB

      // Jenis file yang diizinkan.
      const allowedTypes = ['image/jpeg', 'image/png', 'application/pdf'];

      if (file) {
        // Periksa ukuran file.
        if (file.size > maxFileSize) {
          alert('File size exceeds the limit. Upload a file smaller than 1 MB.');
          return;
        }

        // Periksa jenis file.
        if (!allowedTypes.includes(file.type)) {
          alert('Unsupported file type. Upload a JPEG, PNG, or PDF file.');
          return;
        }

        // File lolos validasi dan dapat diunggah.
        // Anda dapat menulis logika unggahan spesifik di sini.
        console.log('Start uploading file:', file.name);
        // Kode unggahan.
      } else {
        alert('Select a file to upload.');
      }
    }
  </script>
</body>
</html>