@bytescale/upload-widget-angular

中文文档
9.15.0发布于 2024/05/07MITTypeScriptES Module近 30 天下载 1718

Angular File Upload UI Widget — Lightweight & supports: drag and drop, multiple uploads, image cropping, customization & more 🚀 Comes with Cloud Storage 🌐

原始使用文档
文档目录19 节
  1. Installation
  2. Usage
  3. Components & Directives
  4. Option 1: Create an Upload Button — Try on StackBlitz
  5. Option 2: Create a Dropzone — Try on StackBlitz
  6. Result
  7. ⚙️ Configuration
  8. 🏳️ Localization
  9. 🌐 File Management APIs
  10. 🌐 Media Processing APIs (Image/Video/Audio)
  11. Image Processing API (Original Image)
  12. Image Processing API (Transformed Image)
  13. Authentication
  14. API Keys
  15. JWTs
  16. UrlBuilder
  17. 🙋 Can I use my own storage?
  18. 👋 Create your Bytescale Account
  19. License

Bytescale Upload Widget for Angular

Beautiful File Upload Widget for Angular
(Works out-the-box, storage included)



Twitter URL

Get Started — Try on StackBlitz

Upload Widget Demo

100% Serverless File Upload Widget
Powered by Bytescale


Supports: Image Cropping, Video Previews, Document Previews, Drag & Drop, and more...

Full Documentation • Headless SDK • Media Processing APIs • Storage • CDN



Installation

Install via NPM:

npm install @bytescale/upload-widget @bytescale/upload-widget-angular

Or via YARN:

yarn add @bytescale/upload-widget @bytescale/upload-widget-angular

Or via a <script> tag:

<script src="https://js.bytescale.com/upload-widget-angular/v4"></script>

Usage

Add the UploadWidgetModule to your app:

import { NgModule } from "@angular/core";
import { BrowserModule } from "@angular/platform-browser";
import { UploadWidgetModule } from "@bytescale/upload-widget-angular";

import { AppComponent } from "./app.component";

@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule, 
    UploadWidgetModule // <-- Add the UploadWidgetModule here.
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}

Components & Directives

Choose one of these options:

Option 1: Create an Upload Button — Try on StackBlitz

The uploadButton directive displays a file upload modal on click.

Inputs:

  • uploadOptions (required): an object following the UploadWidgetConfig interface.
  • uploadComplete (optional): a callback containing a single parameter — an array of uploaded files.
import { Component } from '@angular/core';
import { UploadWidgetConfig, UploadWidgetResult } from '@bytescale/upload-widget';

@Component({
  selector: 'app-root',
  template: `
    <a href="{{ uploadedFileUrl }}" target="_blank">{{ uploadedFileUrl }}</a>
    <button
      uploadButton
      [uploadOptions]="options"
      [uploadComplete]="onComplete"
    >
      Upload a file...
    </button>
  `,
})
export class AppComponent {
  options: UploadWidgetConfig = {
    apiKey: 'free', // Get API keys from: www.bytescale.com
    multi: false
  };
  onComplete = (files: UploadWidgetResult[]) => {
    this.uploadedFileUrl = files[0]?.fileUrl;
  };
  uploadedFileUrl = undefined;
}

Option 2: Create a Dropzone — Try on StackBlitz

The upload-dropzone component renders an inline drag-and-drop file uploader.

Inputs:

  • options (required): an object following the UploadWidgetConfig interface.
  • onComplete (optional): a callback containing the array of uploaded files as its parameter.
  • onUpdate (optional): same as above, but called after every file upload or removal.
  • width (optional): width of the dropzone.
  • height (optional): height of the dropzone.
import { Component } from "@angular/core";
import { UploadWidgetConfig, UploadWidgetResult, UploadWidgetOnUpdateEvent } from '@bytescale/upload-widget';

@Component({
  selector: "app-root",
  template: `
    <upload-dropzone [options]="options"
                     [onUpdate]="onUpdate"
                     [width]="width"
                     [height]="height"> 
    </upload-dropzone>
  `
})
export class AppComponent {
  options: UploadWidgetConfig = {
    apiKey: 'free', // Get API keys from: www.bytescale.com
    multi: false
  };
  onUpdate = ({ uploadedFiles, pendingFiles, failedFiles }: UploadWidgetOnUpdateEvent) => {
    const uploadedFileUrls = uploadedFiles.map(x => x.fileUrl).join("\n");
    console.log(uploadedFileUrls);
  };
  width = "600px";
  height = "375px";
}

Special behaviour for dropzones:

onComplete only fires if showFinishButton = true (when the user clicks "Finish").

onUpdate must be used when showFinishButton = false.

Default value: showFinishButton = false

Result

The callbacks receive a Array<UploadWidgetResult>:

{
  fileUrl: "https://upcdn.io/FW25...",   // URL to use when serving this file.
  filePath: "/uploads/example.jpg",      // File path (we recommend saving this to your database).

  accountId: "FW251aX",                  // Bytescale account the file was uploaded to.

  editedFile: undefined,                 // Edited file (for image crops). Same structure as below.

  originalFile: {
    fileUrl: "https://upcdn.io/FW25...", // Uploaded file URL.
    filePath: "/uploads/example.jpg",    // Uploaded file path (relative to your raw file directory).
    accountId: "FW251aX",                // Bytescale account the file was uploaded to.
    originalFileName: "example.jpg",     // Original file name from the user's machine.
    file: { ... },                       // Original DOM file object from the <input> element.
    size: 12345,                         // File size in bytes.
    lastModified: 1663410542397,         // Epoch timestamp of when the file was uploaded or updated.
    mime: "image/jpeg",                  // File MIME type.
    metadata: {
      ...                                // User-provided JSON object.
    },
    tags: [
      "tag1",                            // User-provided & auto-generated tags.
      "tag2",
      ...
    ]
  }
}

⚙️ Configuration

All configuration is optional (except for the apiKey field, which is required).

const options = {
  apiKey: "free",                 // Get API keys from: www.bytescale.com
  locale: myCustomLocale,         // EN_US by default. (See "Localization" section below.)
  maxFileCount: 5,                // Unlimited by default (or 1 if multi: false).
  maxFileSizeBytes: 1024 ** 2,    // Unlimited by default.
  mimeTypes: ["image/*"],         // Unrestricted by default. Supports * wildcard suffix.
  multi: false,                   // False by default.
  onInit: ({                      // Exposes lifecycle methods for the component.
    close,                        // Closes the widget when called.
    reset,                        // Resets the widget when called.
    updateConfig                  // Updates the widget's config by passing a new config
  }) => {},                       // object to the method's first parameter.
  onUpdate: (event) => {          // Called each time the Upload Widget's list of files change.
    // event.pendingFiles         // Array of files that are either uploading or queued.
    // event.failedFiles          // Array of files that failed to upload (due to network or validation reasons).
    // event.uploadedFiles        // Array of files that have been uploaded and not removed.
  },
  onPreUpload: async file => ({
    errorMessage: "Uh oh!",       // Displays this validation error to the user (if set).
    transformedFile: file         // Uploads 'transformedFile' instead of 'file' (if set).
  }),
  showFinishButton: true,         // Show/hide the "finish" button in the widget.
  showRemoveButton: true,         // Show/hide the "remove" button next to each file.
  styles: {
    breakpoints: {
      fullScreenWidth: 750,       // Full-screen mode activates when the screen is at or below this width.
      fullScreenHeight: 420       // Full-screen mode activates when the screen is at or below this height.
    },
    colors: {
      primary: "#377dff",         // Primary buttons & links
      active: "#528fff",          // Primary buttons & links (hover). Inferred if undefined.
      error: "#d23f4d",           // Error messages
      shade100: "#333",           // Standard text
      shade200: "#7a7a7a",        // Secondary button text
      shade300: "#999",           // Secondary button text (hover)
      shade400: "#a5a6a8",        // Welcome text
      shade500: "#d3d3d3",        // Modal close button
      shade600: "#dddddd",        // Border
      shade700: "#f0f0f0",        // Progress indicator background
      shade800: "#f8f8f8",        // File item background
      shade900: "#fff"            // Various (draggable crop buttons, etc.)
    },
    fontFamilies: {
      base: "arial, sans-serif"   // Base font family (comma-delimited).
    },
    fontSizes: {
      base: 16                    // Base font size (px).
    }
  },
  path: {                         // Optional: a string (full file path) or object like so:
    fileName: "Example.jpg",      // Supports path variables (e.g. {ORIGINAL_FILE_EXT}).
    folderPath: "/uploads"        // Please refer to docs for all path variables.
  },
  metadata: {
    hello: "world"                // Arbitrary JSON metadata (saved against the file).
  },
  tags: ["profile_picture"],      // Requires a Bytescale account.
  editor: {
    images: {
      allowResizeOnMove: true,    // True by default. If false, prevents cropper from resizing when moved.
      preview: true,              // True by default if cropping is enabled. Previews PDFs and videos too.
      crop: true,                 // True by default.
      cropFilePath: image => {    // Choose the file path used for JSON image crop files.
        const {filePath} = image  // In:  https://www.bytescale.com/docs/types/UploadedFile
        return `${filePath}.crop` // Out: https://www.bytescale.com/docs/types/FilePathDefinition
      },
      cropRatio: 4 / 3,           // Width / Height. Undefined enables freeform (default).
      cropShape: "rect"           // "rect" (default) or "circ".
    }
  },
}

🏳️ Localization

Default is EN_US:

const myCustomLocale = {
  addAnotherFileBtn: "Add another file...",
  addAnotherImageBtn: "Add another image...",
  cancelBtn: "cancel",
  cancelBtnClicked: "cancelled",
  cancelPreviewBtn: "Cancel",
  continueBtn: "Continue",
  cropBtn: "Crop",
  customValidationFailed: "Failed to validate file.",
  doneBtn: "Done",
  fileSizeLimitPrefix: "File size limit:",
  finishBtn: "Finished",
  finishBtnIcon: true,
  imageCropNumberPrefix: "Image",
  maxFilesReachedPrefix: "Maximum number of files:",
  maxImagesReachedPrefix: "Maximum number of images:",
  orDragDropFile: "...or drag and drop a file.",
  orDragDropFileMulti: "...or drag and drop files.",
  orDragDropImage: "...or drag and drop an image.",
  orDragDropImageMulti: "...or drag and drop images.",
  processingFile: "Processing file...",
  removeBtn: "remove",
  removeBtnClicked: "removed",
  submitBtnError: "Error!",
  submitBtnLoading: "Please wait...",
  unsupportedFileType: "File type not supported.",
  uploadFileBtn: "Upload a File",
  uploadFileMultiBtn: "Upload Files",
  uploadImageBtn: "Upload an Image",
  uploadImageMultiBtn: "Upload Images",
  xOfY: "of"
}

🌐 API Support

🌐 File Management APIs

Bytescale provides a wide range of File Management APIs:

🌐 Media Processing APIs (Image/Video/Audio)

Bytescale also provides real-time Media Processing APIs:

Image Processing API (Original Image)

Here's an example using a photo of Chicago:

https://upcdn.io/W142hJk/raw/example/city-landscape.jpg

Image Processing API (Transformed Image)

Using the Image Processing API, you can produce this image:

https://upcdn.io/W142hJk/image/example/city-landscape.jpg
  ?w=900
  &h=600
  &fit=crop
  &f=webp
  &q=80
  &blur=4
  &text=WATERMARK
  &layer-opacity=80
  &blend=overlay
  &layer-rotate=315
  &font-size=100
  &padding=10
  &font-weight=900
  &color=ffffff
  &repeat=true
  &text=Chicago
  &gravity=bottom
  &padding-x=50
  &padding-bottom=20
  &font=/example/fonts/Lobster.ttf
  &color=ffe400

Authentication

Bytescale supports two types of authentication:

API Keys

The Bytescale Upload Widget uses the apiKey parameter to authenticate with Bytescale.

With API key auth, the requester has access to the resources available to the API key:

  • Secret API keys (secret_***) can perform all API operations (see: Bytescale JavaScript SDK).

  • Public API keys (public_***) can perform file uploads and file downloads only. File overwrites, file deletes, and all other destructive operations cannot be performed using public API keys.

You must always use public API keys (e.g. public_***) in your client-side code.

Each API key can have its read/write access limited to a subset of files/folders.

JWTs

JWTs are optional.

With JWTs, users can download private files directly via the URL, as authentication is performed implicitly via a session cookie or via an authorization header if service workers are enabled (see the serviceWorkerScript param on the AuthManager.beginAuthSession method). This allows the browser to display private files in <img>, <video>, and other elements.

With JWTs, users can upload files to per-user folders. This is because the permissions in the JWT's payload can be generated at runtime. The Bytescale Upload Widget internally uses the Bytescale JavaScript SDK to perform file uploads: the Bytescale JavaScript SDK handles the JWT refresh process with your API, requesting new JWTs when required, and includes your JWTs in all subsequent requests to the Bytescale API.

Learn more about the AuthManager and JWTs »

UrlBuilder

The Bytescale JavaScript SDK exports a UrlBuilder to construct URLs from filePaths:

import { UrlBuilder } from "@bytescale/sdk";

Recommended: you should always save filePaths to your DB instead of fileUrls.

Raw Files

To get the URL for the uploaded image /example.jpg in its original form, use the following:

// Returns: "https://upcdn.io/1234abc/raw/example.jpg"
UrlBuilder.url({
  accountId: "1234abc",
  filePath: "/example.jpg"
});

Images

To resize the uploaded image /example.jpg to 800x600, use the following:

// Returns: "https://upcdn.io/1234abc/image/example.jpg?w=800&h=600"
UrlBuilder.url({
  accountId: "1234abc",
  filePath: "/example.jpg",
  options: {
    transformation: "image",
    transformationParams: {
      w: 800,
      h: 600
    }
  }
});

Image Processing API Docs »

Videos

To transcode the uploaded video /example.mov to MP4/H.264 in HD, use the following:

// Returns: "https://upcdn.io/1234abc/video/example.mov?f=mp4-h264&h=1080"
UrlBuilder.url({
  accountId: "1234abc",
  filePath: "/example.mov",
  options: {
    transformation: "video",
    transformationParams: {
      f: "mp4-h264",
      h: 1080
    }
  }
});

Video Processing API Docs »

Audio

To transcode the uploaded audio /example.wav to AAC in 192kbps, use the following:

// Returns: "https://upcdn.io/1234abc/audio/example.wav?f=aac&br=192"
UrlBuilder.url({
  accountId: "1234abc",
  filePath: "/example.wav",
  options: {
    transformation: "audio",
    transformationParams: {
      f: "aac",
      br: 192
    }
  }
});

Audio Processing API Docs »

Archives

To extract the file document.docx from the uploaded ZIP file /example.zip:

// Returns: "https://upcdn.io/1234abc/archive/example.zip?m=extract&artifact=/document.docx"
UrlBuilder.url({
  accountId: "1234abc",
  filePath: "/example.zip",
  options: {
    transformation: "archive",
    transformationParams: {
      m: "extract"
    },
    artifact: "/document.docx"
  }
});

Archive Processing API Docs »

Antivirus

To scan the file example.zip for viruses, use the following:

// Returns: "https://upcdn.io/1234abc/antivirus/example.zip"
UrlBuilder.url({
  accountId: "1234abc",
  filePath: "/example.zip",
  options: {
    transformation: "antivirus"
  }
});

Antivirus API Docs »

🙋 Can I use my own storage?

Bytescale supports AWS S3, Cloudflare R2, Google Storage, DigitalOcean, and Bytescale Storage.

Bytescale Storage Docs »

👋 Create your Bytescale Account

Bytescale is the best way to upload, transform, and serve images, videos, and audio at scale.

Create a Bytescale account »

Full Documentation

License

MIT

版本与发布记录

@bytescale/upload-widget-angular 共发布 21 个版本,首次发布于 2023/09/17;过去 12 个月发布了 0 个版本。

版本发布日期距今
9.15.0latest2024/05/072 年前
9.14.02024/02/062 年前
9.13.02024/01/252 年前
9.12.02024/01/142 年前
9.11.02023/12/272 年前
9.10.02023/12/172 年前

关于 @bytescale/upload-widget-angular 的常见问题

@bytescale/upload-widget-angular 是什么?

Angular File Upload UI Widget — Lightweight & supports: drag and drop, multiple uploads, image cropping, customization & more 🚀 Comes with Cloud Storage 🌐

如何安装 @bytescale/upload-widget-angular?

在项目目录运行 npm install @bytescale/upload-widget-angular,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:@angular/common(>=13)、@angular/core(>=13)、@bytescale/upload-widget(^4.27.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@bytescale/upload-widget-angular 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@bytescale/upload-widget-angular 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@bytescale/upload-widget-angular 可以商用吗?

@bytescale/upload-widget-angular 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@bytescale/upload-widget-angular 的下载量有多少?

根据 npm 官方下载统计,@bytescale/upload-widget-angular 在 2026/10/09 – 2026/11/07 这 30 天内被下载 1,718 次,日均约 57 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@bytescale/upload-widget-angular 还在维护吗?

最新版本 9.15.0 发布于 2024/05/07(2 年前);至今共发布 21 个版本,其中过去 12 个月发布了 0 个;首次发布于 2023/09/17。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。