fixed issue评论附件权限
This commit is contained in:
parent
fce8166ba7
commit
620ddff9bb
|
@ -1,261 +1,261 @@
|
||||||
#coding=utf-8
|
#coding=utf-8
|
||||||
#
|
#
|
||||||
# 文件上传
|
# 文件上传
|
||||||
class AttachmentsController < ApplicationController
|
class AttachmentsController < ApplicationController
|
||||||
before_action :require_login, :check_auth, except: [:show, :preview_attachment, :get_file]
|
before_action :require_login, :check_auth, except: [:show, :preview_attachment, :get_file]
|
||||||
before_action :find_file, only: %i[show destroy]
|
before_action :find_file, only: %i[show destroy]
|
||||||
before_action :attachment_candown, only: [:show]
|
before_action :attachment_candown, only: [:show]
|
||||||
skip_before_action :check_sign, only: [:show, :create]
|
skip_before_action :check_sign, only: [:show, :create]
|
||||||
|
|
||||||
include ApplicationHelper
|
include ApplicationHelper
|
||||||
|
|
||||||
def show
|
def show
|
||||||
# 1. 优先跳到cdn
|
# 1. 优先跳到cdn
|
||||||
# 2. 如果没有cdn,send_file
|
# 2. 如果没有cdn,send_file
|
||||||
if @file.cloud_url.present?
|
if @file.cloud_url.present?
|
||||||
update_downloads(@file)
|
update_downloads(@file)
|
||||||
redirect_to @file.cloud_url and return
|
redirect_to @file.cloud_url and return
|
||||||
end
|
end
|
||||||
|
|
||||||
type_attachment = params[:disposition] || "attachment"
|
type_attachment = params[:disposition] || "attachment"
|
||||||
if type_attachment == "inline"
|
if type_attachment == "inline"
|
||||||
send_file absolute_path(local_path(@file)),filename: @file.title, disposition: 'inline',type: 'application/pdf'
|
send_file absolute_path(local_path(@file)),filename: @file.title, disposition: 'inline',type: 'application/pdf'
|
||||||
elsif type_attachment == "MP4"
|
elsif type_attachment == "MP4"
|
||||||
send_file_with_range absolute_path(local_path(@file)), disposition: 'inline', type: "video/mp4", range: true
|
send_file_with_range absolute_path(local_path(@file)), disposition: 'inline', type: "video/mp4", range: true
|
||||||
else
|
else
|
||||||
send_file(absolute_path(local_path(@file)), filename: @file.title,stream:false, type: @file.content_type.presence || 'application/octet-stream')
|
send_file(absolute_path(local_path(@file)), filename: @file.title,stream:false, type: @file.content_type.presence || 'application/octet-stream')
|
||||||
end
|
end
|
||||||
update_downloads(@file)
|
update_downloads(@file)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def get_file
|
def get_file
|
||||||
normal_status(-1, "参数缺失") if params[:download_url].blank?
|
normal_status(-1, "参数缺失") if params[:download_url].blank?
|
||||||
url = URI.encode(params[:download_url].to_s.gsub("http:", "https:"))
|
url = URI.encode(params[:download_url].to_s.gsub("http:", "https:"))
|
||||||
if url.starts_with?(base_url)
|
if url.starts_with?(base_url)
|
||||||
domain = GiteaService.gitea_config[:domain]
|
domain = GiteaService.gitea_config[:domain]
|
||||||
api_url = GiteaService.gitea_config[:base_url]
|
api_url = GiteaService.gitea_config[:base_url]
|
||||||
url = url.split(base_url)[1].gsub("api", "repos").gsub('?filepath=', '/').gsub('&', '?')
|
url = url.split(base_url)[1].gsub("api", "repos").gsub('?filepath=', '/').gsub('&', '?')
|
||||||
request_url = [domain, api_url, url, "?ref=#{params[:ref]}&access_token=#{current_user&.gitea_token}"].join
|
request_url = [domain, api_url, url, "?ref=#{params[:ref]}&access_token=#{current_user&.gitea_token}"].join
|
||||||
response = Faraday.get(request_url)
|
response = Faraday.get(request_url)
|
||||||
filename = url.to_s.split("/").pop()
|
filename = url.to_s.split("/").pop()
|
||||||
else
|
else
|
||||||
response = Faraday.get(url)
|
response = Faraday.get(url)
|
||||||
filename = params[:download_url].to_s.split("/").pop()
|
filename = params[:download_url].to_s.split("/").pop()
|
||||||
end
|
end
|
||||||
send_data(response.body.force_encoding("UTF-8"), filename: filename, type: "application/octet-stream", disposition: 'attachment')
|
send_data(response.body.force_encoding("UTF-8"), filename: filename, type: "application/octet-stream", disposition: 'attachment')
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
# 1. 本地存储
|
# 1. 本地存储
|
||||||
# 2. 上传到云
|
# 2. 上传到云
|
||||||
begin
|
begin
|
||||||
upload_file = params["file"] || params["#{params[:file_param_name]}"]# 这里的file_param_name是为了方便其他插件名称
|
upload_file = params["file"] || params["#{params[:file_param_name]}"]# 这里的file_param_name是为了方便其他插件名称
|
||||||
uid_logger("#########################file_params####{params["#{params[:file_param_name]}"]}")
|
uid_logger("#########################file_params####{params["#{params[:file_param_name]}"]}")
|
||||||
raise "未上传文件" unless upload_file
|
raise "未上传文件" unless upload_file
|
||||||
|
|
||||||
folder = file_storage_directory
|
folder = file_storage_directory
|
||||||
raise "存储目录未定义" unless folder.present?
|
raise "存储目录未定义" unless folder.present?
|
||||||
|
|
||||||
month_folder = current_month_folder
|
month_folder = current_month_folder
|
||||||
save_path = File.join(folder, month_folder)
|
save_path = File.join(folder, month_folder)
|
||||||
|
|
||||||
ext = file_ext(upload_file.original_filename)
|
ext = file_ext(upload_file.original_filename)
|
||||||
|
|
||||||
local_path, digest = file_save_to_local(save_path, upload_file.tempfile, ext)
|
local_path, digest = file_save_to_local(save_path, upload_file.tempfile, ext)
|
||||||
|
|
||||||
content_type = upload_file.content_type.presence || 'application/octet-stream'
|
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)
|
# remote_path = file_save_to_ucloud(local_path[folder.size, local_path.size], local_path, content_type)
|
||||||
remote_path = nil # TODO 暂时本地上传,待域名配置后方可上传至云端
|
remote_path = nil # TODO 暂时本地上传,待域名配置后方可上传至云端
|
||||||
|
|
||||||
logger.info "local_path: #{local_path}"
|
logger.info "local_path: #{local_path}"
|
||||||
logger.info "remote_path: #{remote_path}"
|
logger.info "remote_path: #{remote_path}"
|
||||||
|
|
||||||
|
|
||||||
disk_filename = local_path[save_path.size + 1, local_path.size]
|
disk_filename = local_path[save_path.size + 1, local_path.size]
|
||||||
#存数据库
|
#存数据库
|
||||||
#
|
#
|
||||||
@attachment = Attachment.where(disk_filename: disk_filename,
|
@attachment = Attachment.where(disk_filename: disk_filename,
|
||||||
author_id: current_user.id,
|
author_id: current_user.id,
|
||||||
cloud_url: remote_path).first
|
cloud_url: remote_path).first
|
||||||
if @attachment.blank?
|
if @attachment.blank?
|
||||||
@attachment = Attachment.new
|
@attachment = Attachment.new
|
||||||
@attachment.filename = upload_file.original_filename
|
@attachment.filename = upload_file.original_filename
|
||||||
@attachment.disk_filename = local_path[save_path.size + 1, local_path.size]
|
@attachment.disk_filename = local_path[save_path.size + 1, local_path.size]
|
||||||
@attachment.filesize = upload_file.tempfile.size
|
@attachment.filesize = upload_file.tempfile.size
|
||||||
@attachment.content_type = content_type
|
@attachment.content_type = content_type
|
||||||
@attachment.digest = digest
|
@attachment.digest = digest
|
||||||
@attachment.author_id = current_user.id
|
@attachment.author_id = current_user.id
|
||||||
@attachment.disk_directory = month_folder
|
@attachment.disk_directory = month_folder
|
||||||
@attachment.cloud_url = remote_path
|
@attachment.cloud_url = remote_path
|
||||||
@attachment.save!
|
@attachment.save!
|
||||||
else
|
else
|
||||||
logger.info "文件已存在,id = #{@attachment.id}, filename = #{@attachment.filename}"
|
logger.info "文件已存在,id = #{@attachment.id}, filename = #{@attachment.filename}"
|
||||||
end
|
end
|
||||||
|
|
||||||
render_json
|
render_json
|
||||||
rescue => e
|
rescue => e
|
||||||
uid_logger_error(e.message)
|
uid_logger_error(e.message)
|
||||||
tip_exception(e.message)
|
tip_exception(e.message)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
begin
|
begin
|
||||||
@file_path = absolute_path(local_path(@file))
|
@file_path = absolute_path(local_path(@file))
|
||||||
#return normal_status(403, "") unless @file.author == current_user
|
#return normal_status(403, "") unless @file.author == current_user
|
||||||
@file.destroy!
|
@file.destroy!
|
||||||
|
|
||||||
delete_file(@file_path)
|
delete_file(@file_path)
|
||||||
normal_status("删除成功")
|
normal_status("删除成功")
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
uid_logger_error(e.message)
|
uid_logger_error(e.message)
|
||||||
tip_exception(e.message)
|
tip_exception(e.message)
|
||||||
raise ActiveRecord::Rollback
|
raise ActiveRecord::Rollback
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# 附件为视频时,点击播放
|
# 附件为视频时,点击播放
|
||||||
def preview_attachment
|
def preview_attachment
|
||||||
attachment = Attachment.find_by(id: params[:id])
|
attachment = Attachment.find_by(id: params[:id])
|
||||||
dir_path = "#{Rails.root}/public/preview"
|
dir_path = "#{Rails.root}/public/preview"
|
||||||
Dir.mkdir(dir_path) unless Dir.exist?(dir_path)
|
Dir.mkdir(dir_path) unless Dir.exist?(dir_path)
|
||||||
if params[:status] == "preview"
|
if params[:status] == "preview"
|
||||||
if system("cp -r #{absolute_path(local_path(attachment))} #{dir_path}/")
|
if system("cp -r #{absolute_path(local_path(attachment))} #{dir_path}/")
|
||||||
render json: {status: 1, url: "/preview/#{attachment.disk_filename}"}
|
render json: {status: 1, url: "/preview/#{attachment.disk_filename}"}
|
||||||
else
|
else
|
||||||
normal_status(-1, "出现错误,请稍后重试")
|
normal_status(-1, "出现错误,请稍后重试")
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if system("rm -rf #{dir_path}/#{attachment.disk_filename}")
|
if system("rm -rf #{dir_path}/#{attachment.disk_filename}")
|
||||||
normal_status(1, "操作成功")
|
normal_status(1, "操作成功")
|
||||||
else
|
else
|
||||||
normal_status(-1, "出现错误,请稍后重试")
|
normal_status(-1, "出现错误,请稍后重试")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def find_file
|
def find_file
|
||||||
@file =
|
@file =
|
||||||
if params[:type] == 'history'
|
if params[:type] == 'history'
|
||||||
AttachmentHistory.find params[:id]
|
AttachmentHistory.find params[:id]
|
||||||
else
|
else
|
||||||
Attachment.find params[:id]
|
Attachment.find params[:id]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def delete_file(file_path)
|
def delete_file(file_path)
|
||||||
File.delete(file_path) if File.exist?(file_path)
|
File.delete(file_path) if File.exist?(file_path)
|
||||||
end
|
end
|
||||||
|
|
||||||
def current_month_folder
|
def current_month_folder
|
||||||
date = Time.now
|
date = Time.now
|
||||||
"#{date.year}/#{date.month.to_s.rjust(2, '0')}"
|
"#{date.year}/#{date.month.to_s.rjust(2, '0')}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def file_ext(file_name)
|
def file_ext(file_name)
|
||||||
ext = ''
|
ext = ''
|
||||||
exts = file_name.split(".")
|
exts = file_name.split(".")
|
||||||
if exts.size > 1
|
if exts.size > 1
|
||||||
ext = ".#{exts.last}"
|
ext = ".#{exts.last}"
|
||||||
end
|
end
|
||||||
ext
|
ext
|
||||||
end
|
end
|
||||||
|
|
||||||
def file_save_to_local(save_path, temp_file, ext)
|
def file_save_to_local(save_path, temp_file, ext)
|
||||||
unless Dir.exists?(save_path)
|
unless Dir.exists?(save_path)
|
||||||
FileUtils.mkdir_p(save_path) ##不成功这里会抛异常
|
FileUtils.mkdir_p(save_path) ##不成功这里会抛异常
|
||||||
end
|
end
|
||||||
|
|
||||||
digest = md5_file(temp_file)
|
digest = md5_file(temp_file)
|
||||||
digest = "#{digest}_#{(Time.now.to_f * 1000).to_i}"
|
digest = "#{digest}_#{(Time.now.to_f * 1000).to_i}"
|
||||||
local_file_path = File.join(save_path, digest) + ext
|
local_file_path = File.join(save_path, digest) + ext
|
||||||
save_temp_file(temp_file, local_file_path)
|
save_temp_file(temp_file, local_file_path)
|
||||||
|
|
||||||
[local_file_path, digest]
|
[local_file_path, digest]
|
||||||
end
|
end
|
||||||
|
|
||||||
def save_temp_file(temp_file, save_file_path)
|
def save_temp_file(temp_file, save_file_path)
|
||||||
File.open(save_file_path, 'wb') do |f|
|
File.open(save_file_path, 'wb') do |f|
|
||||||
temp_file.rewind
|
temp_file.rewind
|
||||||
while (buffer = temp_file.read(8192))
|
while (buffer = temp_file.read(8192))
|
||||||
f.write(buffer)
|
f.write(buffer)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def md5_file(temp_file)
|
def md5_file(temp_file)
|
||||||
md5 = Digest::MD5.new
|
md5 = Digest::MD5.new
|
||||||
temp_file.rewind
|
temp_file.rewind
|
||||||
while (buffer = temp_file.read(8192))
|
while (buffer = temp_file.read(8192))
|
||||||
md5.update(buffer)
|
md5.update(buffer)
|
||||||
end
|
end
|
||||||
md5.hexdigest
|
md5.hexdigest
|
||||||
end
|
end
|
||||||
|
|
||||||
def file_save_to_ucloud(path, file, content_type)
|
def file_save_to_ucloud(path, file, content_type)
|
||||||
ufile = Gitlink::Ufile.new(
|
ufile = Gitlink::Ufile.new(
|
||||||
ucloud_public_key: edu_setting('public_key'),
|
ucloud_public_key: edu_setting('public_key'),
|
||||||
ucloud_private_key: edu_setting('private_key'),
|
ucloud_private_key: edu_setting('private_key'),
|
||||||
ucloud_public_read: true,
|
ucloud_public_read: true,
|
||||||
ucloud_public_bucket: edu_setting('public_bucket'),
|
ucloud_public_bucket: edu_setting('public_bucket'),
|
||||||
ucloud_public_bucket_host: edu_setting('public_bucket_host'),
|
ucloud_public_bucket_host: edu_setting('public_bucket_host'),
|
||||||
ucloud_public_cdn_host: edu_setting('public_cdn_host'),
|
ucloud_public_cdn_host: edu_setting('public_cdn_host'),
|
||||||
)
|
)
|
||||||
File.open(file) do |f|
|
File.open(file) do |f|
|
||||||
ufile.put(path, f, 'Content-Type' => content_type)
|
ufile.put(path, f, 'Content-Type' => content_type)
|
||||||
end
|
end
|
||||||
edu_setting('public_cdn_host') + "/" + path
|
edu_setting('public_cdn_host') + "/" + path
|
||||||
end
|
end
|
||||||
|
|
||||||
def attachment_candown
|
def attachment_candown
|
||||||
unless current_user.admin? || current_user.business?
|
unless current_user.admin? || current_user.business?
|
||||||
candown = true
|
candown = true
|
||||||
unless params[:type] == 'history'
|
unless params[:type] == 'history'
|
||||||
if @file.container && current_user.logged?
|
if @file.container && current_user.logged?
|
||||||
if @file.container.is_a?(Issue)
|
if @file.container.is_a?(Issue)
|
||||||
course = @file.container.project
|
course = @file.container.project
|
||||||
candown = course.member?(current_user) || course.is_public
|
candown = course.member?(current_user) || course.is_public
|
||||||
elsif @file.container.is_a?(Journal)
|
elsif @file.container.is_a?(Journal)
|
||||||
course = @file.container.issue.project
|
course = @file.container.issue.project
|
||||||
candown = course.member?(current_user)
|
candown = course.member?(current_user) || course.is_public
|
||||||
else
|
else
|
||||||
course = nil
|
course = nil
|
||||||
end
|
end
|
||||||
tip_exception(403, "您没有权限进入") if course.present? && !candown
|
tip_exception(403, "您没有权限进入") if course.present? && !candown
|
||||||
tip_exception(403, "您没有权限进入") if @file.container.is_a?(ApplyUserAuthentication)
|
tip_exception(403, "您没有权限进入") if @file.container.is_a?(ApplyUserAuthentication)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def send_file_with_range(path, options = {})
|
def send_file_with_range(path, options = {})
|
||||||
logger.info("########request.headers: #{request.headers}")
|
logger.info("########request.headers: #{request.headers}")
|
||||||
logger.info("########request.headers: #{File.exist?(path)}")
|
logger.info("########request.headers: #{File.exist?(path)}")
|
||||||
|
|
||||||
if File.exist?(path)
|
if File.exist?(path)
|
||||||
size = File.size(path)
|
size = File.size(path)
|
||||||
logger.info("########request.headers: #{request.headers}")
|
logger.info("########request.headers: #{request.headers}")
|
||||||
if !request.headers["Range"]
|
if !request.headers["Range"]
|
||||||
status_code = 200 # 200 OK
|
status_code = 200 # 200 OK
|
||||||
offset = 0
|
offset = 0
|
||||||
length = File.size(path)
|
length = File.size(path)
|
||||||
else
|
else
|
||||||
status_code = 206 # 206 Partial Content
|
status_code = 206 # 206 Partial Content
|
||||||
bytes = Rack::Utils.byte_ranges(request.headers, size)[0]
|
bytes = Rack::Utils.byte_ranges(request.headers, size)[0]
|
||||||
offset = bytes.begin
|
offset = bytes.begin
|
||||||
length = bytes.end - bytes.begin
|
length = bytes.end - bytes.begin
|
||||||
end
|
end
|
||||||
response.header["Accept-Ranges"] = "bytes"
|
response.header["Accept-Ranges"] = "bytes"
|
||||||
response.header["Content-Range"] = "bytes #{bytes.begin}-#{bytes.end}/#{size}" if bytes
|
response.header["Content-Range"] = "bytes #{bytes.begin}-#{bytes.end}/#{size}" if bytes
|
||||||
response.header["status"] = status_code
|
response.header["status"] = status_code
|
||||||
|
|
||||||
send_data IO.binread(path, length, offset), options
|
send_data IO.binread(path, length, offset), options
|
||||||
else
|
else
|
||||||
raise ActionController::MissingFile, "Cannot read file #{path}."
|
raise ActionController::MissingFile, "Cannot read file #{path}."
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue