Edits history of script submission #22499 for ' Put a list of objects in a bucket (s3)'

  • bun
    One script reply has been approved by the moderators
    Ap­pro­ved
    import * as Minio from "minio@7";
    import mime from "mime-types@2";
    
    const MESSAGES_I9 = {
      en: {
        error_mimetype: "File type could not be identified",
        error_file_upload: "Error uploading file (S3)",
      },
      pt_br: {
        error_mimetype: "Tipo do arquivo não pôde ser identificado",
        error_file_upload: "Erro ao enviar arquivo (S3)",
      },
    };
    const MESSAGES = MESSAGES_I9.en;
    
    /****
     * Returns the mimetype and extension of a base64 encoded file
     * @param encoded Base64 encoded file
     * @returns Object with mimetype and extension
     */
    function base64MimeType(encoded: string) {
      let result = null;
    
      if (typeof encoded !== "string") {
        return result;
      }
    
      const match = encoded.match(/data:([a-zA-Z0-9]+\/[a-zA-Z0-9-.+]+).*,.*/);
      if (match && match.length) {
        result = {
          mimetype: match[1],
          extension: mime.extension(match[1]),
        };
      }
    
      return result;
    }
    
    /****
     * Uploads a list of files to S3
     * @param s3 S3 resource
     * @param files Array of base64 encoded files
     * @returns Object with error_count and array of results (files URLs or error messages)
     *
     * Detects file type/extension using base64 header (e.g. "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAA...").
     * The output of File Input component can be used as parameter for this function.
     */
    type S3 = {
      endPoint: string;
      port: number;
      useSSL: boolean;
      pathStyle: boolean;
      bucket: string;
      accessKey: string;
      secretKey: string;
      region: string;
    };
    export async function main(s3: S3, files: string[]) {
      if (files.length <= 0) {
        return;
      }
    
      const s3client = new Minio.Client(s3);
    
      const out: any[] = [];
      let error_count = 0;
    
      await Promise.all(
        files.map(async (file: string) => {
          try {
            const mime_data = base64MimeType(file)!;
            if (mime_data) {
              const now = new Date();
              const pad = (n: number) => String(n).padStart(2, "0");
              const timestamp =
                `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}` +
                `-${pad(now.getHours())}-${pad(now.getMinutes())}-${pad(now.getSeconds())}`;
              const file_name =
                timestamp +
                "-" +
                Math.random().toString(36).substring(2, 8) +
                "." +
                mime_data.extension;
              const base64Data = file.replace(/^data:\w+\/\w+;base64,/, "");
              const bytes = Buffer.from(base64Data, "base64");
    
              await s3client.putObject(s3.bucket, file_name, bytes, bytes.length, {
                "Content-Type": mime_data.mimetype,
              });
    
              const url = `https://${s3["endPoint"]}/${s3["bucket"]}/${file_name}`;
              out.push({
                success: true,
                url,
              });
            } else {
              out.push({
                success: false,
                message: MESSAGES.error_mimetype,
              });
              error_count++;
            }
          } catch (error) {
            out.push({
              success: false,
              message: `${MESSAGES.error_file_upload} (S3): ${error.message}`,
            });
            error_count++;
          }
        }),
      );
    
      return { error_count, files: out };
    }
    

    Submitted by hugo989 6 days ago