“Isn’t it just uploading a picture? How hard can it be?”

I thought contemptuously when I needed to upload my blog images to Aliyun via the API of Flutter.

Then time unknowingly jumped to two days later ~~

Preface: Why did it take so long?

Part of it was going through the documentation, looking at the documentation, trying to figure out what would work.

The other part is spent on signature attempts. (Signature verification is really complicated)

The next section is spent on trial and error with the putObject and postObject methods.

Sunshine always after the wind and rain, tortuous road ah finally succeeded ~

Find a plan to step on the pit

First step, first of allGo to the websiteFind ali Cloud OSS has relevant SDK available.

Check out the website and unsurprisingly, the Flutter is a little-used gadget and ali still hasn’t released the SDK at this point.

The second step is to find the signature verification method and parameter API of THE API request upload

Signature verification official website description

Header Indicates the specific generation mode of the signature

Api address: oss-example.oss-cn-hangzhou.aliyuncs.com

Oss-example uses its own bucket name instead

Step 3: Find a successful image upload API

The first thing I found was the putObject method (documentation), and after referring to the official Java code and finally adding a usable signature to the header, I kept getting XML parameter errors and stuff. Because I didn’t pass the XML parameter, I just put image/ JPG, so I was confused and confused.

Finally try using postObject(The document) It worked.

Two. Feasible detailed route

  • The first reaction is to try to find the official SDK if the Flutter platform is developed

SDK List link

  • Step 2, then start signing by referring to the official signature document.

Pseudocode of official note:

/// Method for calculating the Authorization field Authorization = "OSS "+ AccessKeyId + ":" + Signature Signature = base64(hmac-sha1(AccessKeySecret, VERB + "\n" + Content-MD5 + "\n" + Content-Type + "\n" + Date + "\n" + CanonicalizedOSSHeaders + CanonicalizedResource))Copy the code

The actual written DART code:

class OssUtils {
  static var f = DateFormat('EEE, dd MMM yyyy HH:mm:ss');
  ///Get the signature string
  static String buildSignature(String httpMethod, String resourcePath, RequestOptions request) {
    var Date = f.format(DateTime.now().toUtc()) + " GMT";
    request.headers['Date']=Date;
    var CanonicalizedOSSHeaders = buildCanonicalizedOSSHeaders(request);
    var CanonicalizedResource = resourcePath;
    final headers = request.headers.map((key, value) => MapEntry(key.toLowerCase(), value));
    var string = StringBuffer().. writeln(httpMethod);// Md5 contains MD5
    if (headers.containsKey(HttpHeaders.contentMD5Header)) {
      string.write(headers[HttpHeaders.contentMD5Header]);
    }
    string.writeln();
    // Type contains type
    if(headers.containsKey(HttpHeaders.contentTypeHeader)) { string.write(headers[HttpHeaders.contentTypeHeader]); } string.writeln(); string .. writeln(Date) .. write(CanonicalizedOSSHeaders) .. write(CanonicalizedResource);var Signature = base64.encode(Hmac(sha1, AccessKeySecret.toBytes()).convert(string.toString().toBytes()).bytes);
    var Authorization = "OSS " + AccessKeyId + ":" + Signature;
    return Authorization;
  }

  static String buildCanonicalizedOSSHeaders(RequestOptions request) {
    final canonicalOssHeadersString = StringBuffer(a);final headers = request.headers;
    final canonicalizedOssHeadersToSign = SplayTreeMap<String.String> (); headers.forEach((key, value) {String lowerKey = key.toLowerCase();
      if (lowerKey.startsWith("x-oss-")) { canonicalizedOssHeadersToSign[lowerKey] = value.toString().trim(); }});// Append canonicalized oss headers to sign to canonical stringcanonicalizedOssHeadersToSign.forEach((key, value) { canonicalOssHeadersString .. write(key) .. write(':')
        ..writeln(value);
    });
    returncanonicalOssHeadersString.toString(); }}Copy the code
  1. Finally, add the signature to Headers by calling the generate signature method in the DIO interceptor
_ossdio! .interceptors.add(InterceptorsWrapper( onRequest: (options, handler) {var Authorization = OssUtils.buildSignature(options.method, "/guuguohome/", options);
      options.headers["Authorization"] = Authorization;
      handler.next(options);
    },
    onResponse: _onResponse));
Copy the code
  • Next, upload the image using postObject (Official document)

Future<String> uploadToOss(File image) async {
  var host = "${bucket}.oss-cn-hangzhou.aliyuncs.com";
  var url = "https://${host}";
  ///The file name is used as the key
  var fileName = path.split(image.path).last;
  var policyData = {
    "expiration": "The 2314-12-01 T12:00:00) 000 z".// A hundred years later
    "conditions": [{"bucket": bucket},
    ]
  };
  var policy = base64.encode(json.encode(policyData).toBytes());
  var signature = base64.encode(Hmac(sha1, AccessKeySecret.toBytes()).convert(policy.toBytes()).bytes);
  final data = FormData.fromMap({
    "file": await MultipartFile.fromFile(
      image.path, // Image path
      filename: fileName, // Image name
    ),
    "key": fileName,
    "policy": policy,  // It must be
    "Signature": signature,  // It must be
    "OSSAccessKeyId": AccessKeyId,
  });

  ///Refer to https://help.aliyun.com/document_detail/31978.html? SPM = a2c4g. 11186623.6.1673.50 d8c2502BbrCV
  Options? options = Options(headers: {
    "x-oss-storage-class": "IA".// Low frequency storage
    "Host": host,
    "Content-Encoding": "utf-8"});final res = await getOssDio().post(url, options: options, data: data);
  return url + "/" + fileName;

}
Copy the code
  • Finally, the upload is done

If you go to ali Cloud OSS console, you can see that bucket has an extra image file.

Congratulations, congratulations

Look at the pictures

After uploading an image, you naturally need to get the URL to access the image.

There are two situations

The first is simple: a public read bucket

Make sure that the bucket permissions are set to public

With public read permissions, it’s easy to view images, just concatenate url links with a key.

// Splice rule
var url="https://${bucket}.oss-cn-hangzhou.aliyuncs.com/${objectkey}"
/ / example: https://guuguohome.oss-cn-hangzhou.aliyuncs.com/temp_103830-05dbfb795c3c84e2.jpg
Copy the code

The second,Reference documentationFor a link

Look at the document look at the document look at the document

End four.

“Isn’t it just uploading a picture? How hard can it be?”

I muttered as I looked at the picture I had finally uploaded successfully.