当前位置: 首页 > 软件库 > 程序开发 > >

ember-active-storage

Direct uploads with Rails' Active Storage
授权协议 MIT License
开发语言 JavaScript
所属分类 程序开发
软件类型 开源软件
地区 不详
投 递 者 公羊浩阔
操作系统 跨平台
开源组织
适用人群 未知
 软件概览

ember-active-storage

CI

Installation

ember install @algonauti/ember-active-storage

Usage

The addon provides an activeStorage service that allows you to:

  • send files to your Rails backend's direct upload controller;
  • listen to upload progress events.

Assuming your template has a file input like:

<input type="file" {{on "change" (fn this.upload)}} />

and your ember model has an avatar attribute defined as has_one_attached :avatar on its corresponding Active Record model, then in your component (or controller) the upload action would look like:

import Component from '@glimmer/component';
import { action } from '@ember/object';
import { tracked } from '@glimmer/tracking';
import { inject as service } from '@ember/service';

export default class UploadComponent extends Component {
  @service
  activeStorage;

  @tracked
  uploadProgress = 0;

  @action
  upload(event) {
    const files = event.target.files;
    if (files) {
      const directUploadURL = '/rails/active_storage/direct_uploads';

      for (var i = 0; i < files.length; i++) {
        this.activeStorage
          .upload(files.item(i), directUploadURL, {
            onProgress: (progress) => {
              this.uploadProgress = progress;
            },
          })
          .then((blob) => {
            const signedId = blob.signedId;

            this.model.avatar = signedId;
          });
      }
    }
  }
}
  • directUploadURL is the path referencing ActiveStorage::DirectUploadsController on your Rails backend (or a custom one built on top of that).
  • The uploadProgress property will hold a value between 0 and 100 that you might use in your template to show upload progress.
  • After the upload promise is resolved and signedId is set in your model, when a model.save() is triggered, the Rails backend will use such signedId to associate an ActiveStorage::Attachment record to your backend model's record.

loadstart, load, loadend, error, abort, timeout events invokes onLoadstart, onLoad, onLoadend, onError, onAbort, onTimeout accordingly. For example; If you want to use the loadend event in your app, you can use like;

import Component from '@glimmer/component';
import { action } from '@ember/object';
import { tracked } from '@glimmer/tracking';
import { inject as service } from '@ember/service';

export default class UploadComponent extends Component {
  @service
  activeStorage;

  @tracked
  uploadProgress = 0;

  @action
  upload(event) {
    const files = event.target.files;
    if (files) {
      const directUploadURL = '/rails/active_storage/direct_uploads';

      for (var i = 0; i < files.length; i++) {
        this.activeStorage
          .upload(files.item(i), directUploadURL, {
            onProgress: (progress) => {
              this.uploadProgress = progress;
            },
            onLoadend: (event) => {
              debug(`Event captured ${event}`); // https://developer.mozilla.org/en-US/docs/Web/API/ProgressEvent
            },
          })
          .then((blob) => {
            const signedId = blob.signedId;

            this.model.avatar = signedId;
          });
      }
    }
  }
}

If you need the actual XHR object in your app, you can use the onXHROpened event. It returns the XHR object reference. For example:

import Component from '@glimmer/component';
import { action } from '@ember/object';
import { tracked } from '@glimmer/tracking';
import { inject as service } from '@ember/service';

export default class UploadComponent extends Component {
  @service
  activeStorage;

  @tracked
  uploadProgress = 0;
  
  @tracked
  xhrs = [];

  @action
  upload(event) {
    const files = event.target.files;
    if (files) {
      const directUploadURL = '/rails/active_storage/direct_uploads';

      for (var i = 0; i < files.length; i++) {
        this.activeStorage
          .upload(files.item(i), directUploadURL, {
            onProgress: (progress) => {
              this.uploadProgress = progress;
            },
            onXHROpened: (xhr) => {
              this.xhrs.push(xhr);  // so you can loop over this.xhrs and invoke abort()
            },
          })
          .then((blob) => {
            const signedId = blob.signedId;

            this.model.avatar = signedId;
          });
      }
    }
  }
}

There is an ember-active-storage ENV config with only one parameter called url. With this config help, you can omit the upload url now. For example:

ENV['ember-active-storage'] = {
  url: 'http://your-domain/rails/active_storage/direct_uploads',
};

Now you can call the upload function without the upload url.

import Component from '@glimmer/component';
import { action } from '@ember/object';
import { tracked } from '@glimmer/tracking';
import { inject as service } from '@ember/service';

export default class UploadComponent extends Component {
  @service
  activeStorage;

  @tracked
  uploadProgress = 0;

  @action
  upload(event) {
    const files = event.target.files;
    if (files) {
      for (var i = 0; i < files.length; i++) {
        this.activeStorage
          .upload(files.item(i), {
            onProgress: (progress) => {
              this.uploadProgress = progress;
            },
          })
          .then((blob) => {
            const signedId = blob.signedId;

            this.model.avatar = signedId;
          });
      }
    }
  }
}

Sending authentication headers

It's pretty common that you want to protect with authentication the direct uploads endpoint on your Rails backend. If that's the case, the activeStorage service will need to send authentication headers together with the direct upload request.

To achieve that, you'll need to extend the activeStorage service provided by the addon and add a headers computed property. For example, if you're using ember-simple-auth, it will be a 2-steps process. First you'll need to define an authenticatedHeaders computed property in your session service, like this:

// app/services/session.js
import Service from '@ember/service';
import { inject as service } from '@ember/service';

export default class MySessionService extends Service {
  @service
  session;

  get authenticatedHeaders() {
    const { access_token } = this.session.authenticated;

    return { Authorization: `Bearer ${access_token}` };
  }
}

Then, you will alias that property in your activeStorage service, like this:

// app/services/active-storage.js
import ActiveStorage from '@algonauti/ember-active-storage/services/active-storage';
import { inject as service } from '@ember/service';

export default class ActiveStorageService extends ActiveStorage {
  @service('my-session')
  session;

  get headers() {
    this.session.authenticatedHeaders;
  }
}

Also note: if the download endpoint is protected as well, and you're using an ajax request to download files, then don't forget to include the same headers in that request as well.

Contributing

Installation

  • git clone <repository-url>
  • cd ember-active-storage
  • yarn install

Linting

  • yarn lint:js
  • yarn lint:js --fix

Running tests

  • ember test – Runs the test suite on the current Ember version
  • ember test --server – Runs the test suite in "watch mode"
  • yarn test – Runs ember try:each to test your addon against multiple Ember versions

Running the dummy application

For more information on using ember-cli, visit https://ember-cli.com/.

License

This project is licensed under the MIT License.

  •   上周主管说,要把每次开过的发票,要下载成Pdf的文件,然后就实时的将这些发票存到云上面去。  就是这个Microsoft Azure ,微软的亲儿子。 先把代码贴上来吧,挺简单的。 1 ##1.链接账号密码 2 StorageCredentials storageCredentials = new StorageCredentials( 3

  • 分区存储设备 分区存储设备是一类存储设备,其地址空间被划分为具有不同于常规存储设备的写入约束的区域 zones。 原理 分区存储设备的区域 必须按顺序写入。 设备地址空间的每个zone 都有一个写入指针wp,用于跟踪下一次写入的位置。 区域中的数据不能被直接覆盖。 必须首先使用特殊命令(zone reset)擦除该区域。 下图说明了这一原理。

  • Table  Entity Group Transactions (SaveChangesOptions.Batch) (In Sample1) Here’s a more complete description from the “Programming Table Storage” whitepaper:" For the entities storedwithin the same tab

  • 1.新建Container public void NewContainer(string name, int access /* 2=public container, 1=public blob, 0=private */) { if (CloudStorageAccount == null) return; name = No

  • Availability Durability Scalability 10-20 rack storage Windows Azure Storage Stamps Stream Layer (Duratable) -Files,Blob Patition Layer  -Blob -Queue -Entity Patition Master -Range Partition -Index Ra

  •      It doesn't matter what programming language u use,it's all about the usage of variable---storage management. 1.Static & Dynamic static: Global constants and the other information/data generated b

  • Queue Get messages in a batch (In Sample 1) Poison message : use dequeuecount (In Sample 1) Delete message: always add try-catch at multiple consumers situation (In Sample 1) Always add time sleep to

  • 转:   问:Active/Active与Active/Passive阵列之间的区别是什么?哪一种技术更好? 答:   拥有两个或者更多控制器的存储阵列(SCSI,FC,iSCSI以及NAS)可以配置成为Active/Active模式或者Active/Passive模式。 Active/Passive意味着一个控制器为主动处理I/O请求,而另外一个处于空闲状态,以备用于在主控制器出现故障或者处于离

 相关资料
  • 描述 (Description) :active伪类用于向激活的元素添加特殊效果。 在 ... 块中定义伪类时,应注意以下几点 - a:hover必须在a:link和a:在CSS定义中访问才能生效。 a:主动必须在a:hover in CSS定义后才能生效。 伪类名称不区分大小写。 伪类与CSS类不同,但它们可以组合在一起。 可能的值 (Possible Values) color - 任何有效的

  • Framework7 uses so called "active state" to highlight links and buttons when you tap them. It is done to make F7 app behave like native app, not like web app. Active state is a part of built-in Fast C

  • Active Merchant 是 Shopify 电子商务系统的提取(extraction) 。它发展了 Ruby on Rails 网络应用程序的用途,能够作为一个 Rails 插件实现无缝集成,当然它也可以单独作为一个 Ruby 库使用。 Active Merchant 自创建以后就被用于现在 Ruby 应用程序中,用来处理金融交易 。 下面程序示例展示了如何使用个人信用卡购买东西的过程:

  • Active CMS 是一个非常简单的内容管理系统,主要用于个人网站。使用 OOP PHP5/MySQL 和 jQuery/Ajax 开发,管理界面很轻量级,使用简单。

  • Active Server Pages (ASP) 是服务器端的脚本编写环境,您可用它来创建动态 Web 页或生成功能强大的 Web 应用程序。ASP 页是包括 HTML 标记、文本和脚本命令的文件。ASP 页可调用 ActiveX 组件来执行任务,例如连接到数据库或进行商务计算。通过 ASP,可为您的 Web 页添加交互内容或用 HTML 页构成整个 Web 应用程序,这些应用程序使用 HTML

  • NGINX Plus supports Active Health Checks, To use active health checks in the Ingress controller:1. HTTP Readiness Probe in the templates of your application pods apiVersion: apps/v1 kind: Deployment m