In this paper, a personal blog address: www.leafage.top/posts/detai…

Leafage-ms project has been written for a long time, but the function of uploading files has not been completed. Before, I read the documents of Qiniuyun for several times, but failed. Today, I made up my mind to solve this problem, so I started looking for materials, documents and examples again.

The project is built using vite. Js, and uses typescript. There are almost no examples on the web.

Qiniu-js is upload and crypto-js is encryption tool for token generation. The installation command is as follows:

yarn add crypto-js qiniu-js -D
Copy the code

Create the upload.ts file under the tool/plug-in directory and refer to the official document to write the uploading method, encryption and token generation method. First is the uploading method, and the final code is as follows:

import * as qiniu from 'qiniu-js';
import CryptoJS from 'crypto-js'

// Request the interface to upload images
export function uploadFile(file: File) {
    const uptoken = getToken("ss"."xx"."xx");
    const key = file.name;
    const config = {
        useCdnDomain: true.region: qiniu.region.z2,
        forceDirect: true // Whether all uploads are in direct mode
    };
    const putExtra: any = {
        fname: file.name, // The original file name
        mimeType: ['image/png'.'image/jpeg'.'image/gif'] // Specifies the type of files to be uploaded. If the value is null, the file type is not limited.
    };
    return qiniu.upload(file, key, uptoken, putExtra, config);
}
Copy the code

Note that the final return is the result of the upload() execution, which is an object with next, error and complete in it.

The uploadFile() method needs to be exposed for use in the component

The three parameters of getToken() method are accessKey, secretKey and bucketName. You need to log in to your qiuniuyun account to view the parameters. After logging in, click your profile picture and then click Key Management, you can see the final code of getToken() method:

function getToken(access_key: string, secret_key: string, bucketname: string) {
    // Construct the policy
    var putPolicy = {
        "scope": bucketname,
        "deadline": 3600 + Math.floor(Date.now() / 1000)}var encoded = base64Encode(utf16to8(JSON.stringify(putPolicy)));
    var hash = CryptoJS.HmacSHA1(encoded, secret_key);
    // Construct the credentials
    var encodedSign = hash.toString(CryptoJS.enc.Base64).replace(/\//g.'_').replace(/\+/g.The '-');
    var uploadToken = access_key + ':' + encodedSign + ':' + encoded;
    return uploadToken;
}
Copy the code

The code implementation of the base64Encode() and UTf16to8 () methods in getToken() is as follows:

function base64Encode(str: string) {
    var out, i, len;
    var c1, c2, c3;
    len = str.length;
    i = 0;
    out = "";
    var base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
    while (i < len) {
        c1 = str.charCodeAt(i++) & 0xff;
        if (i == len) {
            out += base64EncodeChars.charAt(c1 >> 2);
            out += base64EncodeChars.charAt((c1 & 0x3) < <4);
            out += "= =";
            break;
        }
        c2 = str.charCodeAt(i++);
        if (i == len) {
            out += base64EncodeChars.charAt(c1 >> 2);
            out += base64EncodeChars.charAt(((c1 & 0x3) < <4) | ((c2 & 0xF0) > >4));
            out += base64EncodeChars.charAt((c2 & 0xF) < <2);
            out += "=";
            break;
        }
        c3 = str.charCodeAt(i++);
        out += base64EncodeChars.charAt(c1 >> 2);
        out += base64EncodeChars.charAt(((c1 & 0x3) < <4) | ((c2 & 0xF0) > >4));
        out += base64EncodeChars.charAt(((c2 & 0xF) < <2) | ((c3 & 0xC0) > >6));
        out += base64EncodeChars.charAt(c3 & 0x3F);
    }
    return out;
}
Copy the code
function utf16to8(str: string) {
    var out, i, len, c;
    out = "";
    len = str.length;
    for (i = 0; i < len; i++) {
        c = str.charCodeAt(i);
        if ((c >= 0x0001) && (c <= 0x007F)) {
            out += str.charAt(i);
        } else if (c > 0x07FF) {
            out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F));
            out += String.fromCharCode(0x80 | ((c >> 6) & 0x3F));
            out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
        } else {
            out += String.fromCharCode(0xC0 | ((c >> 6) & 0x1F));
            out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F)); }}return out;
}
Copy the code

The entire upload method is completed and then used in the component as shown in the following example:

import { uploadFile } from ".. /.. /plugins/upload";
Copy the code

Add controls to HTML as shown in the following example:

<div class="mx-auto text-center">
    <div class="text-center text-gray-600">
          <label
              for="file-upload"
              class="relative cursor-pointer bg-white rounded-md text-gray-400 hover:text-indigo-500"
           >
                <svg
                   class="mx-auto h-8 w-8"
                   stroke="currentColor"
                   fill="none"
                   viewBox="0 0 48 48"
                   aria-hidden="true"
                >
                   <path
                      d="M28 8H12a4 4 0 00-4 4v20m32-12v8m0v8a4 4 0 01-4 4H12a4 4 0 01-4-4v-4m32-4l-3.172-3.172 A4 4 0 00-5.656 0L28 28M8 32l9.172-9.172 A4 4 0 015.656 0L28 28m0 0L4 4m4-24h8-4-4v8-12 4h.02"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                   />
                    </svg>
                    <input
                      id="file-upload"
                      name="cover"
                      type="file"
                      class="sr-only"
                      accept="image/png,image/jpeg,image/jpg"
                      @change="uploadImage($event.target.files)"
                    />
               </label>
          </div>
    <p class="text-xs text-gray-500">png, jpeg, jpg</p>
    <p class="text-xs text-gray-500">up to 2MB</p>
</div>
Copy the code

The uploadFile method is called within the uploadFile method. The following example uploads only one file:

// Upload the file
    uploadImage(files: Array<File>) {
      if (files.length > 0) {
        uploadFile(files[0]).subscribe({
          next: (result) = >{},error: () = >{},complete: (e) = > {
            letdata = { ... this.postsData,cover: "https://cdn.leafage.top/" + e.key,
            };
            this.postsData = data; }}); }},Copy the code