Ruby on Rails Example

Caution

For server security, please refer to the link below when handling this work.

[Software Security Weakness Diagnosis Guide]

The example below was written against Ruby 2.5.1 and Rails 5.2.3.

The carrierwave gem is used as the uploader for file upload. See the carrierwave installation guide for setup.

The example uses /upload as the API for image, video, and file uploads, and /import as the API for document import.

// synapeditor.config.js
{
  'editor.import.api':       '/import',
  'editor.upload.image.api': '/upload',
  'editor.upload.video.api': '/upload',
  'editor.upload.file.api':  '/upload'
}

1. Create a File Uploader

Caution

The file-upload portion of the sample code below is intentionally minimal and lacks proper security handling.

For the file-upload portion, use what is already in place inside your project, and refer to the code below for the integration portion only.

rails generate uploader File
# ./app/uploaders/file_uploader.rb
class FileUploader < CarrierWave::Uploader::Base
  storage :file

  def store_dir
    'uploads/'
  end

  def filename
    "#{secure_token}.#{file.extension}" if original_filename.present?
  end

  protected

  def secure_token
    var = :"@#{mounted_as}_secure_token"
    model.instance_variable_get(var) || model.instance_variable_set(var, SecureRandom.uuid)
  end
end

2. Create a Model

rails generate model UploadFile
# ./app/models/upload_file.rb
class UploadFile < ApplicationRecord
  mount_uploader :file, FileUploader
end

3. Create a Controller

rails generate controller UploadFile
# ./app/controllers/upload_file_controller.rb
class UploadFileController < ApplicationController
  skip_before_action :verify_authenticity_token   # csrf_token

  def upload
    uploaded = UploadFile.create(file: params[:file])
    render json: { 'uploadPath': uploaded.file.url }
  end

  def import
    root_path = Rails.root
    uploaded  = UploadFile.create(file: params[:file])

    # 1. Document conversion
    input_file_path = uploaded.file.path
    input_file_name = File.basename(input_file_path)
    output_dir_name = File.basename(input_file_name, File.extname(input_file_name))

    converter_path  = "%s/sedocConverter/sedocConverter_exe" % [root_path]
    font_dir_path   = "%s/fonts" % [root_path]
    output_dir_path = "%s/public/output/%s" % [root_path, output_dir_name]
    tmp_dir_path    = "%s/tmp" % [root_path]

    system("%s -pz -f %s %s %s %s" % [converter_path, font_dir_path, input_file_path, output_dir_path, tmp_dir_path])

    # 2. Serialize .pb
    pb_file_path = "%s/document.pb" % [output_dir_path]
    a_file       = File.open(pb_file_path, 'r')
    a_serialized = []
    if a_file
      a_file.sysread(16)
      a_file.each_byte do |byte|
        a_serialized.push(byte & 0xFF)
      end
    end

    # 3. Clean up
    File.delete(input_file_path) if File.exist?(input_file_path)
    File.delete(pb_file_path)    if File.exist?(pb_file_path)

    render json: {
      'importPath':     "/output/%s" % [File.basename(output_dir_path)],
      'serializedData': a_serialized
    }
  end
end

4. Database Migration

# Add a 'file' column on UploadFile
rails generate migration AddFileToUploadFile file:string
rake db:migrate

5. Routes

# ./config/routes.rb
Rails.application.routes.draw do
  post 'import' => 'upload_file#import'
  post 'upload' => 'upload_file#upload'
end

Related Information