Search code examples
javascriptruby-on-railsamazon-web-servicesshrineroda

problem while trying to implement a drag and drop direct upload with shrine direct_upload for aws rails 5.2


Code:

image_upload.js

function uploadAttachment(attachment) {
  var file = attachment.file;
  var form = new FormData;
  form.append("Content-Type", file.type);
  form.append("forum_post_photo[image]", file);

  var xhr = new XMLHttpRequest;
  xhr.open("POST", "/forum_post_photos.json", true);
  xhr.setRequestHeader("X-CSRF-Token", Rails.csrfToken());

  xhr.upload.onprogress = function(event){
    var progress = event.loaded / event.total * 100;
    attachment.setUploadProgress(progress);
  }

  xhr.onload = function(){
    if (xhr.status == 201){
      var data = JSON.parse(xhr.responseText);
      return attachment.setAttributes({
        url: data.image_url,
        href: data.image_url
      })
    }
  }

  return xhr.send(form);
}

document.addEventListener("trix-attachment-add", function(event){
  var attachment = event.attachment;

  if (attachment.file){
    console.log('new',attachment);
    return uploadAttachment(attachment);
  }
});

shrine.rb

require "shrine/storage/s3"

s3_options = {
  bucket:            Rails.application.credentials.aws[:bucket_name], # required
  access_key_id:     Rails.application.credentials.aws[:access_key_id],
  secret_access_key: Rails.application.credentials.aws[:secret_access_key],
  region:            Rails.application.credentials.aws[:bucket_region],
}

Shrine.storages = {
  cache: Shrine::Storage::S3.new(prefix: "cache",upload_options: { acl: "public-read" } , **s3_options),
  store: Shrine::Storage::S3.new(prefix: "store",upload_options: { acl: "public-read" } ,**s3_options),
}

Shrine.plugin :activerecord
Shrine.plugin :presign_endpoint, presign_options: -> (request) {
  filename = request.params["filename"]
  type     = request.params["type"]

  {
    content_disposition:    "inline; filename=\"#{filename}\"", # set download filename
    content_type:           type,                               # set content type (required if using DigitalOcean Spaces)
    content_length_range:   0..(10*1024*1024),                  # limit upload size to 10 MB
  }
}
Shrine.plugin :restore_cached_data

trix-upload

require "shrine/storage/s3"

s3_options = {
  bucket:            Rails.application.credentials.aws[:bucket_name], # required
  access_key_id:     Rails.application.credentials.aws[:access_key_id],
  secret_access_key: Rails.application.credentials.aws[:secret_access_key],
  region:            Rails.application.credentials.aws[:bucket_region],
}

Shrine.storages = {
  cache: Shrine::Storage::S3.new(prefix: "cache",upload_options: { acl: "public-read" } , **s3_options),
  store: Shrine::Storage::S3.new(prefix: "store",upload_options: { acl: "public-read" } ,**s3_options),
}

Shrine.plugin :activerecord
Shrine.plugin :presign_endpoint, presign_options: -> (request) {
  filename = request.params["filename"]
  type     = request.params["type"]

  {
    content_disposition:    "inline; filename=\"#{filename}\"", # set download filename
    content_type:           type,                               # set content type (required if using DigitalOcean Spaces)
    content_length_range:   0..(10*1024*1024),                  # limit upload size to 10 MB
  }
}
Shrine.plugin :restore_cached_data
 trix-upload
function uploadAttachment(attachment) {
  var file = attachment.file;
  var form = new FormData;
  form.append("Content-Type", file.type);
  form.append("forum_post_photo[image]", file);

  var xhr = new XMLHttpRequest;
  xhr.open("POST", "/forum_post_photos.json", true);
  xhr.setRequestHeader("X-CSRF-Token", Rails.csrfToken());

  xhr.upload.onprogress = function(event){
    var progress = event.loaded / event.total * 100;
    attachment.setUploadProgress(progress);
  }

  xhr.onload = function(){
    if (xhr.status == 201){
      var data = JSON.parse(xhr.responseText);
      return attachment.setAttributes({
        url: data.image_url,
        href: data.image_url
      })
    }
  }

  return xhr.send(form);
}

document.addEventListener("trix-attachment-add", function(event){
  var attachment = event.attachment;

  if (attachment.file){
    console.log('new',attachment);
    return uploadAttachment(attachment);
  }
});

Long story short I am using trix for rich text on a forum, all models and controllers are working, I am attempting to direct_upload on with a drag and drop into the editor as shown here but can't get the js right.

all other config is set direct from the documentation

Photos are being uploaded to my aws but all are expiring in a few mins

example: https://sprout-free-forum-photos.s3.amazonaws.com/store/de6271df193b0ae16e14c3297c58c363.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAINSUNFHRJEDP6TQA%2F20181027%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20181027T192116Z&X-Amz-Expires=900&X-Amz-SignedHeaders=host&X-Amz-Signature=a4c9da3b5933ca29954dfaf11e592543c69a5a7ad1d4dcd3b70747ef0a695c38

even with my bucket set to public read

any help would be great I am lost!

This is current site live and here is my full git


Solution

  • Experienced this problem today also.

    Also using Shrine with AWS S3, and Trix in an old rails app.

    What I noticed is that the images are present in the S3 server, its just the URLs that Trix is using that does not work.

    After searching some other similar questions, ran into this: https://stackoverflow.com/a/51197576/2561325

    The answer there is from one of the maintainer of the shrine gem. All you have to do is apply the public settings in your shrine initializer in config/initializers/shrine.rb.

    My problem is fixed now, images used by Trix editor not expiring.