|
|
|
|
#coding=utf-8
|
|
|
|
|
#
|
|
|
|
|
# 文件上传
|
|
|
|
|
class AttachmentsController < ApplicationController
|
|
|
|
|
before_action :require_login
|
|
|
|
|
before_action :find_file, only: %i[show destroy]
|
|
|
|
|
|
|
|
|
|
include ErrorCommon
|
|
|
|
|
include ApplicationHelper
|
|
|
|
|
|
|
|
|
|
def show
|
|
|
|
|
# 1. 优先跳到cdn
|
|
|
|
|
# 2. 如果没有cdn,send_file
|
|
|
|
|
if @file.cloud_url.present?
|
|
|
|
|
update_downloads(@file)
|
|
|
|
|
redirect_to @file.cloud_url and return
|
|
|
|
|
end
|
|
|
|
|
send_file absolute_path(local_path(@file)), type: @file.content_type
|
|
|
|
|
|
|
|
|
|
update_downloads(@file)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def create
|
|
|
|
|
# 1. 本地存储
|
|
|
|
|
# 2. 上传到云
|
|
|
|
|
upload_file = params["file"] || params["#{params[:file_param_name]}"] # 这里的file_param_name是为了方便其他插件名称
|
|
|
|
|
uid_logger("#########################file_params####{params["#{params[:file_param_name]}"]}")
|
|
|
|
|
raise "未上传文件" unless upload_file
|
|
|
|
|
|
|
|
|
|
folder = edu_setting('attachment_folder')
|
|
|
|
|
raise "存储目录未定义" unless folder.present?
|
|
|
|
|
|
|
|
|
|
month_folder = current_month_folder
|
|
|
|
|
save_path = File.join(folder, month_folder)
|
|
|
|
|
|
|
|
|
|
ext = file_ext(upload_file.original_filename)
|
|
|
|
|
|
|
|
|
|
local_path, digest = file_save_to_local(save_path, upload_file.tempfile, ext)
|
|
|
|
|
|
|
|
|
|
content_type = upload_file.content_type.presence || 'application/octet-stream'
|
|
|
|
|
|
|
|
|
|
remote_path = file_save_to_ucloud(local_path[folder.size, local_path.size], local_path, content_type)
|
|
|
|
|
|
|
|
|
|
logger.info "local_path: #{local_path}"
|
|
|
|
|
logger.info "remote_path: #{remote_path}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
disk_filename = local_path[save_path.size + 1, local_path.size]
|
|
|
|
|
#存数据库
|
|
|
|
|
#
|
|
|
|
|
@attachment = Attachment.where(disk_filename: disk_filename,
|
|
|
|
|
author_id: current_user.id,
|
|
|
|
|
cloud_url: remote_path).first
|
|
|
|
|
|
|
|
|
|
if @attachment.blank?
|
|
|
|
|
@attachment = Attachment.new
|
|
|
|
|
@attachment.filename = upload_file.original_filename
|
|
|
|
|
@attachment.disk_filename = local_path[save_path.size + 1, local_path.size]
|
|
|
|
|
@attachment.filesize = upload_file.tempfile.size
|
|
|
|
|
@attachment.content_type = content_type
|
|
|
|
|
@attachment.digest = digest
|
|
|
|
|
@attachment.author_id = current_user.id
|
|
|
|
|
@attachment.disk_directory = month_folder
|
|
|
|
|
@attachment.cloud_url = remote_path
|
|
|
|
|
@attachment.save!
|
|
|
|
|
else
|
|
|
|
|
logger.info "文件已存在,id = #{@attachment.id}, filename = #{@attachment.filename}"
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
render_json
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def destroy
|
|
|
|
|
begin
|
|
|
|
|
@file_path = absolute_path(local_path(@file))
|
|
|
|
|
#return normal_status(403, "") unless @file.author == current_user
|
|
|
|
|
@file.destroy!
|
|
|
|
|
|
|
|
|
|
delete_file(@file_path)
|
|
|
|
|
rescue Exception => e
|
|
|
|
|
uid_logger_error(e.message)
|
|
|
|
|
tip_exception(e.message)
|
|
|
|
|
raise ActiveRecord::Rollback
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
private
|
|
|
|
|
def find_file
|
|
|
|
|
@file =
|
|
|
|
|
if params[:type] == 'history'
|
|
|
|
|
AttachmentHistory.find params[:id]
|
|
|
|
|
else
|
|
|
|
|
Attachment.find params[:id]
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def delete_file(file_path)
|
|
|
|
|
File.delete(file_path) if File.exist?(file_path)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def current_month_folder
|
|
|
|
|
date = Time.now
|
|
|
|
|
"#{date.year}/#{date.day.to_s.rjust(2, '0')}"
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def file_ext(file_name)
|
|
|
|
|
ext = ''
|
|
|
|
|
exts = file_name.split(".")
|
|
|
|
|
if exts.size > 1
|
|
|
|
|
ext = ".#{exts.last}"
|
|
|
|
|
end
|
|
|
|
|
ext
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def file_save_to_local(save_path, temp_file, ext)
|
|
|
|
|
unless Dir.exists?(save_path)
|
|
|
|
|
FileUtils.mkdir_p(save_path) ##不成功这里会抛异常
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
digest = md5_file(temp_file)
|
|
|
|
|
digest = "#{digest}_#{Time.now.to_i}"
|
|
|
|
|
local_file_path = File.join(save_path, digest) + ext
|
|
|
|
|
save_temp_file(temp_file, local_file_path)
|
|
|
|
|
|
|
|
|
|
[local_file_path, digest]
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def save_temp_file(temp_file, save_file_path)
|
|
|
|
|
File.open(save_file_path, 'wb') do |f|
|
|
|
|
|
temp_file.rewind
|
|
|
|
|
while (buffer = temp_file.read(8192))
|
|
|
|
|
f.write(buffer)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def md5_file(temp_file)
|
|
|
|
|
md5 = Digest::MD5.new
|
|
|
|
|
temp_file.rewind
|
|
|
|
|
while (buffer = temp_file.read(8192))
|
|
|
|
|
md5.update(buffer)
|
|
|
|
|
end
|
|
|
|
|
md5.hexdigest
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def file_save_to_ucloud(path, file, content_type)
|
|
|
|
|
ufile = Educoder::Ufile.new(
|
|
|
|
|
ucloud_public_key: edu_setting('public_key'),
|
|
|
|
|
ucloud_private_key: edu_setting('private_key'),
|
|
|
|
|
ucloud_public_read: true,
|
|
|
|
|
ucloud_public_bucket: edu_setting('public_bucket'),
|
|
|
|
|
ucloud_public_bucket_host: edu_setting('public_bucket_host'),
|
|
|
|
|
ucloud_public_cdn_host: edu_setting('public_cdn_host'),
|
|
|
|
|
)
|
|
|
|
|
File.open(file) do |f|
|
|
|
|
|
ufile.put(path, f, 'Content-Type' => content_type)
|
|
|
|
|
end
|
|
|
|
|
edu_setting('public_cdn_host') + "/" + path
|
|
|
|
|
end
|
|
|
|
|
end
|