如何编写用于正确下载和下载文件的控制器



我将Rails作为后端和前端Angular 5。如何在Rails上正确地编写控制器和路由,以便将来可以使用Angular上传和下载文件?我使用的常规控制器不工作:

class FilesController < ApplicationController
before_action :set_file, only: [:show, :update, :destroy]
def index
@files = File.all
render json: @files
end
def show
render json: @file
end
def create
@file = File.new(files_params)
if @file.save
render json: @file, status: :created, location: @file
else
render json: @file.errors, status: :unprocessable_entity
end
end
def update
if @file.update(files_params)
render json: @file
else
render json: @file.errors, status: :unprocessable_entity
end  
end
def destroy
@file.destroy
end
private
def set_file
@file = File.find(params[:id])
end
def files_params
params.require(:file).permit!
end
end

文件:

ID:          NUMBER
NAME:        VARCHAR2
FILE_NAME:   VARCHAR2
CONTENT:     BLOB
FILE_TYPE:   VARCHAR2

TL;博士:

我将使用解决方案2而不是解决方案1,除非您真的打算将File数据作为JSON响应的一部分。

解决方案1:JSON包含文件的Base64编码字符串

app/models/file.rb:

class File < ApplicationRecord
def as_json(options = nil)
super(
except: [:content],
methods: [:content_encoded]
)
end
def content_encoded
Base64.strict_encode64(content)
end
end

然后,在您的JS:中

// do AJAX call to FilesController#index...
// sample JSON response:
// [
//   { "id": 1, "name": "...", "file_name": "...", "file_type": "...", "content_encoded": "SGVsbG8gCiB3b3JsZCBoYWhhaGE=", "created_at": "...", "updated_at": "..." },
//   { "id": 2, "name": "...", "file_name": "...", "file_type": "...", "content_encoded": "WW93cyB5b3dzIHlvd3Mh", "created_at": "...", "updated_at": "..." }
// ]
// then, say we now have this response body Object (named `data`)
Object.forEach(data, function(file) {
// atob decodes Base64-encoded-string into Binary-string
var fileContent = atob(file.content_encoded)
});

解决方案2:JSON包含文件的URL字符串

app/controllers/files_controller.rb:

class FilesController < ApplicationController
before_action :set_file, only: [:show, :update, :destroy, :content]
def index
@files = File.all
json_response = @files.collect do |file|
file.as_json(
except: :content
).merge(
content_url: content_file_url(file)
)
end
render json: json_response
end
def content
send_data @file.content
end
# ...
end

app/config/routes.rb

Rails.application.routes.draw do
resources :files do
# will generate a route: GET /files/:id/content as `content_file_url`
get :content, on: :member
end
end

然后,在您的JS 中

// do AJAX call to FilesController#index...
// sample JSON response:
// [
//   { "id": 1, "name": "...", "file_name": "...", "file_type": "...", "content_url": "http://localhost:3000/files/1/content", "created_at": "...", "updated_at": "..." },
//   { "id": 2, "name": "...", "file_name": "...", "file_type": "...", "content_url": "http://localhost:3000/files/2/content", "created_at": "...", "updated_at": "..." }
// ]
// then, say we now have the response body Object (named `data`)
Object.forEach(data, function(file) {
console.log(file.content_url)
});

最新更新