全部产品
Search
文档中心

Object Storage Service:Unggah formulir

更新时间:Jul 02, 2025

Unggah formulir memungkinkan Anda langsung mengunggah objek ke Object Storage Service (OSS) menggunakan formulir HTML standar dari aplikasi web. Setelah objek dipilih di halaman front-end, browser memulai permintaan PostObject untuk mengunggah objek langsung ke server OSS tanpa melibatkan server situs web. Hal ini mengurangi beban kerja pada server situs web serta meningkatkan efisiensi dan stabilitas pengunggahan objek.

Batasan

Ukuran objek yang ingin diunggah menggunakan unggah formulir tidak boleh melebihi 5 GB.

Skenario

Unggah formulir banyak digunakan dalam aplikasi web, termasuk tetapi tidak terbatas pada skenario berikut:

  • Pengunggahan data pengguna: Pengguna mengunggah avatar, foto KTP, atau bahan verifikasi identitas lainnya saat mendaftarkan akun. Mereka juga dapat mengunggah avatar baru atau gambar latar belakang saat memodifikasi informasi di pusat pribadi.

  • Berbagi dan penyimpanan objek: Pengguna mengunggah objek dalam berbagai format, seperti dokumen, gambar, file audio, dan file video, ke Alibaba Cloud untuk penyimpanan dan berbagi menggunakan formulir pada disk online dan platform kerja kolaboratif.

  • Pembuatan dan publikasi konten: Pengguna menulis artikel di platform seperti blog, forum, dan komunitas tanya jawab, serta mengunggah gambar dan lampiran sebagai pelengkap konten menggunakan formulir.

  • Pengelolaan e-commerce: Pedagang mengunggah informasi seperti gambar produk, dokumen deskripsi detail, dan kualifikasi di latar belakang platform e-commerce. Konsumen juga dapat mengunggah persyaratan faktur atau bahan pendukung lainnya selama proses pembelian.

  • Platform pendidikan online: Siswa mengunggah tugas atau proyek, seperti dokumen, PPT, dan file video. Guru mengunggah materi pengajaran dan bahan kursus.

  • Situs rekrutmen: Pencari kerja mengunggah resume, portofolio, dan bahan lainnya. Perusahaan mengunggah bahan seperti logo perusahaan dan dokumen rekrutmen saat memposting posisi.

  • Kuesioner dan umpan balik: Pengguna mengunggah bukti tambahan atau dokumen penjelasan saat mengisi kuesioner online.

  • Kolaborasi pengembangan perangkat lunak: Pengembang mengunggah file kode atau dokumen proyek dari platform hosting kode seperti GitHub dan GitLab.

Solusi

Klien meminta tanda tangan dan kebijakan POST yang diperlukan oleh permintaan PostObject dari server aplikasi. Kemudian, klien dapat menggunakan tanda tangan dan kebijakan POST untuk mengunggah objek tanpa menggunakan SDK OSS. Anda dapat menggunakan kebijakan POST yang dihasilkan oleh server aplikasi untuk membatasi atribut objek, seperti ukuran dan jenis objek. Solusi ini cocok untuk skenario di mana Anda ingin mengunggah objek menggunakan formulir HTML. Namun, solusi ini tidak mendukung unggah multipart atau unggah yang dapat dilanjutkan. Untuk informasi lebih lanjut, lihat PostObject.

Gambar berikut menunjukkan cara mengunggah objek dari klien ke OSS menggunakan tanda tangan dan kebijakan POST yang diperoleh dari server aplikasi.

  1. Klien meminta informasi seperti tanda tangan dan kebijakan POST dari server aplikasi.

  2. Server aplikasi menghasilkan dan mengembalikan informasi seperti tanda tangan dan kebijakan POST ke klien.

  3. Klien menggunakan informasi seperti tanda tangan dan kebijakan POST untuk memanggil operasi PostObject guna mengunggah objek ke OSS menggunakan formulir HTML.

  4. OSS mengembalikan respons sukses ke klien.

Prosedur

  1. Server menghasilkan informasi seperti tanda tangan dan kebijakan POST.

    • Contoh proyek: postsignature.zip

    • Contoh

      Kode contoh berikut menunjukkan cara server aplikasi menghasilkan tanda tangan dan kebijakan POST untuk PostObject:

      Catatan

      Kode contoh dapat diterapkan di Function Compute. oss-upload-post-signature-app

      Python

      import os
      from hashlib import sha1 as sha
      import json
      import base64
      import hmac
      import datetime
      import time
      
      # Dapatkan AccessKey ID dari variabel lingkungan OSS_ACCESS_KEY_ID.
      access_key_id = os.environ.get('OSS_ACCESS_KEY_ID')
      # Dapatkan Rahasia AccessKey dari variabel lingkungan OSS_ACCESS_KEY_SECRET.
      access_key_secret = os.environ.get('OSS_ACCESS_KEY_SECRET')
      # Ganti <YOUR_BUCKET> dengan nama bucket.
      bucket = '<YOUR_BUCKET>'
      # Set host ke nilai dalam format BucketName.Endpoint. Ganti <YOUR_BUCKET> dengan nama bucket. Ganti <YOUR_ENDPOINT> dengan endpoint wilayah tempat bucket berada, seperti oss-cn-hangzhou.aliyuncs.com.
      host = 'https://<YOUR_BUCKET>.<YOUR_ENDPOINT>'
      # Tentukan awalan dalam nama objek yang ingin Anda unggah ke OSS.
      upload_dir = 'user-dir-prefix/'
      # Tentukan periode validitas. Unit: detik.
      expire_time = 3600
      
      
      def generate_expiration(seconds):
          """
          Waktu kedaluwarsa dihitung berdasarkan periode validitas yang ditentukan. Unit: detik.
          :param seconds: periode validitas (detik).
          :return: string waktu dalam standar ISO 8601. Contoh: 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 tanda tangan.
          :param access_key_secret: Rahasia AccessKey yang memiliki izin untuk mengakses bucket.
          :param expiration: waktu ketika tanda tangan kedaluwarsa. Tentukan waktu dalam standar ISO 8601 dalam format yyyy-MM-ddTHH:mm:ssZ. Contoh: 2014-12-01T12:00:00.000Z.
          :param conditions: kondisi kebijakan yang dapat digunakan untuk membatasi nilai yang dapat Anda tentukan selama unggah formulir.
          :param policy_extra_props: parameter kebijakan tambahan. Anda dapat meneruskan parameter tambahan sebagai dict.
          :return: string tanda tangan.
          """
          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 = {
              # Tentukan periode validitas.
              "expiration": generate_expiration(expire_time),
              # Tentukan kondisi kebijakan.
              "conditions": [
                  # Jika success_action_redirect tidak ditentukan, kode status HTTP 204 dikembalikan setelah objek diunggah.
                  ["eq", "$success_action_status", "200"],
                  # Nilai bidang formulir harus dimulai dengan awalan tertentu. Misalnya, jika nilai bidang kunci dimulai dengan user/user1, kondisinya adalah ["starts-with", "$key", "user/user1"].
                  ["starts-with", "$key", upload_dir],
                  # Tentukan ukuran minimum dan maksimum objek yang dapat diunggah. Unit: byte.
                  ["content-length-range", 1, 1000000],
                  # Tentukan jenis file yang diizinkan.
                  ["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
              # Tentukan parameter tambahan.
          }
          return json.dumps(response)
      

      Java

      import com.aliyun.help.demo.uploading_to_oss_directly_postsignature.config.OssConfig;
      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;
      import com.aliyun.oss.OSSClientBuilder;
      import org.springframework.context.annotation.Configuration;
      import org.springframework.context.annotation.Bean;
      import javax.annotation.PreDestroy;
      
      @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("Menangkap OSSException, yang berarti permintaan Anda sampai di OSS, "
                      + "tetapi ditolak dengan respons kesalahan karena alasan tertentu.");
              // Asumsikan metode ini ada.
              System.out.println("Kode Status HTTP: " + oe.getRawResponseError()); 
              System.out.println("Pesan Kesalahan: " + oe.getErrorMessage());
              System.out.println("Kode Kesalahan:       " + oe.getErrorCode());
              System.out.println("ID Permintaan:      " + oe.getRequestId());
              System.out.println("ID Host:           " + oe.getHostId());
          } catch (ClientException ce) {
              System.out.println("Menangkap ClientException, yang berarti klien mengalami "
                      + "masalah internal serius saat mencoba berkomunikasi dengan OSS, "
                      + "seperti tidak dapat mengakses jaringan.");
              System.out.println("Pesan Kesalahan: " + ce.getMessage());
          } finally {
              if (ossClient != null) {
                  ossClient.shutdown();
              }
              return response.toString();
          }
        }
      }
      
      @Configuration
      public class OssConfig {
          /**
           * Ganti <YOUR-ENDPOINT> dengan endpoint wilayah tempat bucket berada, seperti oss-cn-hangzhou.aliyuncs.com.
           */
          private String endpoint = "<YOUR-ENDPOINT>";
          /**
           * Ganti <YOUR-BUCKET> dengan nama bucket.
           */
          private String bucket = "<YOUR-BUCKET>";
          /**
           * Tentukan awalan dalam nama objek di OSS.
           */
          private String dir = "user-dir-prefix/";
          /**
           * Tentukan periode validitas. Unit: detik.
           */
          private long expireTime = 3600;
          /**
           * Buat host.
           */
          private String host = "http://" + bucket + "." + endpoint;
          /**
           * Dapatkan AccessKey ID dari variabel lingkungan ALIBABA_CLOUD_ACCESS_KEY_ID.
           */
          private String accessKeyId = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
          /**
           * Dapatkan Rahasia AccessKey dari variabel lingkungan ALIBABA_CLOUD_ACCESS_KEY_SECRET.
           */
          private String accessKeySecret = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
      
          private OSS ossClient;
          @Bean
          public OSS getOssClient() {
              ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
              return ossClient;
          }
          @Bean
          public String getHost() {
              return host;
          }
          @Bean
          public String getAccessKeyId() {
              return accessKeyId;
          }
          @Bean
          public long getExpireTime() {
              return expireTime;
          }
          @Bean
          public String getDir() {
              return dir;
          }
      
          @PreDestroy
          public void onDestroy() {
              ossClient.shutdown();
          }
      }
      
      

      Go

      package main
      
      import (
          "crypto/hmac"
          "crypto/sha1"
          "encoding/base64"
          "encoding/json"
          "fmt"
          "io"
          "net/http"
          "os"
          "time"
      )
      
      var (
          // Dapatkan AccessKey ID dari variabel lingkungan OSS_ACCESS_KEY_ID.
          accessKeyId = os.Getenv("OSS_ACCESS_KEY_ID")
          // Dapatkan Rahasia AccessKey dari variabel lingkungan OSS_ACCESS_KEY_SECRET.
          accessKeySecret = os.Getenv("OSS_ACCESS_KEY_SECRET")
          // Tentukan host. Format: BucketName.Endpoint. Ganti ${your-bucket} dengan nama bucket. Ganti ${your-endpoint} dengan endpoint OSS, seperti oss-cn-hangzhou.aliyuncs.com.
          host = "http://${your-bucket}.${your-endpoint}"
          // Tentukan awalan dalam nama objek yang ingin Anda unggah ke OSS.
          uploadDir = "user-dir-prefix/"
          // Tentukan periode validitas. Unit: 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
          var condition []string
          condition = append(condition, "starts-with")
          condition = append(condition, "$key")
          condition = append(condition, uploadDir)
          config.Conditions = append(config.Conditions, condition)
          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, pastikan bahwa 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");
      // Tentukan host. Format: <YOUR-BUCKET>.<YOUR-ENDPOINT>.
      $host = 'http://<YOUR-BUCKET>.<YOUR-ENDPOINT>';
      // Tentukan awalan dalam nama objek yang ingin Anda unggah.
      $dir = 'user-dir-prefix/';          
      
      $now = time();
      // Tentukan waktu kedaluwarsa kebijakan. Jika waktu kedaluwarsa berakhir, akses ditolak. Dalam contoh ini, waktu kedaluwarsa diatur menjadi 10 detik.
      $expire = 30;  
      $end = $now + $expire;
      $expiration = gmt_iso8601($end);
      
      // Tentukan ukuran maksimum objek yang dapat diunggah.
      $condition = array(0 => 'content-length-range', 1 => 0, 2 => 1048576000);
      $conditions[] = $condition;
      
      // Tentukan objek yang dapat diunggah. Dalam contoh ini, hanya objek yang namanya dimulai dengan nilai parameter $dir yang dapat diunggah. Ini adalah pengaturan opsional yang mencegah objek diunggah ke direktori berbeda di bucket menggunakan 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 = {
        // Dapatkan AccessKey ID dari variabel lingkungan ALIBABA_CLOUD_ACCESS_KEY_ID.
        accessKeyId: process.env.ALIBABA_CLOUD_ACCESS_KEY_ID,
        // Dapatkan Rahasia AccessKey dari variabel lingkungan ALIBABA_CLOUD_ACCESS_KEY_SECRET.
        accessKeySecret: process.env.ALIBABA_CLOUD_ACCESS_KEY_SECRET,
        // Ganti <YOUR-BUCKET> dengan nama bucket.
        bucket: "<YOUR-BUCKET>",
        // Tentukan awalan dalam nama objek yang ingin Anda unggah 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();
        // Tentukan periode validitas tanda tangan. Unit: detik.
        date.setSeconds(date.getSeconds() + 3600);
        const policy = {
          expiration: date.toISOString(),
          conditions: [
            // Tentukan batas ukuran pada objek yang dapat diunggah.
            ["content-length-range", 0, 1048576000],
            // Tentukan bucket ke mana objek 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 jalur folder publik ke subfolder templates dalam folder saat ini.
      set :public_folder, File.dirname(__FILE__) + '/templates'
      
      # Dapatkan AccessKey ID dari variabel lingkungan ALIBABA_CLOUD_ACCESS_KEY_ID.
      $access_key_id = ENV['ALIBABA_CLOUD_ACCESS_ID']
      # Dapatkan Rahasia AccessKey dari variabel lingkungan ALIBABA_CLOUD_ACCESS_KEY_SECRET.
      $access_key_secret = ENV['ALIBABA_CLOUD_ACCESS_SECRET']
      
      # Tentukan host. Host dalam format <bucketname>.<endpoint>.
      $host = 'http://<bucketname>.<endpoint>';
      
      # Tentukan awalan dalam nama objek yang ingin Anda unggah.
      $upload_dir = 'user-dir-prefix/'
      # Tentukan periode validitas. Unit: 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 berjalan pada: 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 berjalan pada: 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;
              // Dapatkan AccessKey ID dari variabel lingkungan ALIBABA_CLOUD_ACCESS_KEY_ID.
              public string AccessKeyId { get; set; } = Environment.GetEnvironmentVariable("ALIBABA_CLOUD_ACCESS_KEY_ID");
              // Dapatkan Rahasia AccessKey dari variabel lingkungan ALIBABA_CLOUD_ACCESS_KEY_SECRET.
              public string AccessKeySecret { get; set; } = Environment.GetEnvironmentVariable("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
              // Tentukan host. Format: BucketName.Endpoint. Ganti <YOUR-BUCKET> dengan nama bucket. Ganti <YOUR-ENDPOINT> dengan endpoint wilayah tempat bucket berada, seperti oss-cn-hangzhou.aliyuncs.com.
              public string Host { get; set; } = "<YOUR-BUCKET>.<YOUR-ENDPOINT>";
              // Tentukan awalan dalam nama objek yang ingin Anda unggah ke OSS.
              public string UploadDir { get; set; } = "user-dir-prefix/";
              // Tentukan periode validitas. Unit: 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 ke 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)));
                  }
              }
          }
      }
      
  2. Klien menggunakan informasi seperti tanda tangan dan kebijakan POST untuk memanggil operasi PostObject guna mengunggah objek ke OSS menggunakan formulir HTML.

    JavaScript digunakan dalam contoh berikut:

    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Unggah objek ke OSS</title>
    </head>
    <body>
      <div class="container">
        <form>
          <div class="mb-3">
            <label for="file" class="form-label">Pilih objek</label>
            <input type="file" class="form-control" id="file" name="file" required>
          </div>
          <button type="submit" class="btn btn-primary">Unggah</button>
        </form>
      </div>
      &  <script type="text/javascript">
          const form = document.querySelector('form');
          const fileInput = document.querySelector('#file');
          form.addEventListener('submit', (event) => {
            event.preventDefault();
            let file = fileInput.files[0];
            let filename = fileInput.files[0].name;
            fetch('/get_post_signature_for_oss_upload', { method: 'GET' })
              .then(response => 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);
                // Setel file ke bidang formulir terakhir. Tidak diperlukan urutan tertentu untuk bidang formulir lainnya.
                formData.append('file', file);
                fetch(data.host, { method: 'POST', body: formData},).then((res) => {
                  console.log(res);
                  alert ('Objek Diunggah');
                });
              })
              .catch(error => {
                console.log('Terjadi kesalahan saat mendapatkan parameter unggah OSS:', error);
              });
          });
      </script>
    </body>
    </html>
    

Catatan penggunaan

Keamanan data

Penimpaan objek

Secara default, OSS menimpa objek yang ada dengan objek yang diunggah dengan nama yang sama. Anda dapat menggunakan metode berikut untuk mencegah objek yang ada ditimpa secara tidak sengaja:

  • Aktifkan versioning untuk bucket

    Jika Anda mengaktifkan versioning untuk bucket, objek yang ditimpa di bucket disimpan sebagai versi sebelumnya. Anda dapat memulihkan versi sebelumnya dari objek kapan saja. Untuk informasi lebih lanjut, lihat Versioning.

  • Sertakan parameter x-oss-forbid-overwrite dalam permintaan unggah

    Anda dapat menambahkan parameter x-oss-forbid-overwrite ke bidang formulir permintaan unggah dan atur parameter ini ke true. Jika Anda mengunggah objek dengan nama yang sama dengan objek yang ada, objek gagal diunggah dan kode kesalahan FileAlreadyExists dikembalikan. Jika Anda tidak menambahkan parameter ini ke header permintaan atau jika Anda mengatur parameter ini ke false, objek akan menimpa objek yang ada dengan nama yang sama di bucket.

Pengunggahan berizin

  • OSS menyediakan kontrol akses pada tingkat bucket dan objek untuk mencegah pihak ketiga mengunggah data ke bucket Anda tanpa izin. Untuk informasi lebih lanjut, lihat Kontrol akses.

  • Anda dapat menggunakan URL yang ditandatangani untuk memberikan izin kepada pengguna pihak ketiga mengunggah objek tertentu. Dengan cara ini, pengguna pihak ketiga dapat mengunggah data tanpa kredensial akses atau otorisasi. OSS menyimpan data yang diunggah sebagai objek di bucket. Untuk informasi lebih lanjut, lihat Pengunggahan objek menggunakan URL yang ditandatangani.

Biaya permintaan PUT

Jika Anda ingin mengunggah sejumlah besar objek dan menetapkan kelas penyimpanan objek ke Deep Cold Archive, Anda akan dikenakan biaya tinggi untuk biaya permintaan PUT. Kami merekomendasikan agar Anda menetapkan kelas penyimpanan objek ke Standar saat mengunggah objek, dan mengonfigurasi aturan siklus hidup untuk mengonversi kelas penyimpanan objek Standar ke Deep Cold Archive. Ini membantu mengurangi biaya permintaan PUT.

Pengunggahan objek ke bucket tempat OSS-HDFS diaktifkan

Untuk menjaga stabilitas OSS-HDFS dan mencegah hilangnya data, jangan mengunggah objek ke direktori .dlsdata/ dari bucket tempat OSS-HDFS diaktifkan menggunakan metode yang tidak didukung oleh OSS-HDFS.

Peningkatan kinerja unggah

Jika Anda mengunggah sejumlah besar objek dan nama objek tersebut berisi awalan berurutan seperti cap waktu dan huruf, beberapa indeks objek mungkin disimpan dalam satu partisi. Akibatnya, latensi meningkat saat sejumlah besar permintaan dikirim untuk menanyakan objek-objek tersebut. Jika Anda ingin mengunggah sejumlah besar objek, kami merekomendasikan agar Anda menggunakan awalan acak alih-alih awalan berurutan untuk menentukan nama objek. Untuk informasi lebih lanjut, lihat Praktik terbaik kinerja OSS.