You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

zipdown_controller.rb 11 kB

​
​
​
​
​
​
​
​
​
11 years ago
​
10 years ago
​
​
​
​
​
​
​
​
11 years ago
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
10 years ago
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
12 years ago
12 years ago
​
​
​
12 years ago
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
10 years ago
​
​
​
​
​
​
​
​
​
12 years ago
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. #coding=utf-8
  2. require "base64"
  3. require 'zip'
  4. class ZipdownController < ApplicationController
  5. #查找项目(课程)
  6. before_filter :find_project_by_bid_id, :only => [:assort]
  7. #检查权限
  8. #勿删 before_filter :authorize, :only => [:assort,:download_user_homework]
  9. SAVE_FOLDER = "#{Rails.root}/files"
  10. OUTPUT_FOLDER = "#{Rails.root}/files/archiveZip"
  11. MAX_PATH = 50
  12. #统一下载功能
  13. def download
  14. if User.current.logged?
  15. begin
  16. if params[:base64file]
  17. file = decode64(params[:base64file])
  18. send_file "#{OUTPUT_FOLDER}/#{file}", :filename => filename_for_content_disposition(file), :type => detect_content_type(file)
  19. else
  20. send_file "#{OUTPUT_FOLDER}/#{params[:file]}", :filename => filename_for_content_disposition(params[:filename]), :type => detect_content_type(params[:file])
  21. end
  22. rescue => e
  23. render file: 'public/no_file_found.html'
  24. end
  25. else
  26. render_403
  27. end
  28. end
  29. #一个作业下所有文件打包下载,只有admin和课程老师有权限
  30. def assort
  31. if params[:obj_class] == "Bid"
  32. bid = Bid.find params[:obj_id]
  33. render_403 if User.current.allowed_to?(:as_teacher,bid.courses.first)
  34. file_count = 0
  35. bid.homeworks.map { |homework| file_count += homework.attachments.count}
  36. if file_count > 0
  37. zipfile = zip_bid bid
  38. else
  39. zipfile = {:message => "no file"}
  40. end
  41. elsif params[:obj_class] == "HomeworkCommon"
  42. homework = HomeworkCommon.find params[:obj_id]
  43. render_403 if User.current.allowed_to?(:as_teacher,homework.course)
  44. file_count = 0
  45. homework.student_works.map { |work| file_count += work.attachments.count}
  46. if file_count > 0
  47. zipfile = zip_homework_common homework
  48. else
  49. zipfile = {:message => "no file"}
  50. end
  51. else
  52. logger.error "[ZipDown#assort] ===> #{params[:obj_class]} unKown !!"
  53. end
  54. respond_to do |format|
  55. format.json {
  56. render json: zipfile.to_json
  57. }
  58. end
  59. end
  60. #下载某一学生的作业的所有文件
  61. def download_user_homework
  62. homework = HomeworkAttach.find params[:homework]
  63. if User.current.admin? || User.current.member_of_course?(homework.bid.courses.first)
  64. if homework != nil
  65. unless homework.attachments.empty?
  66. zipfile = zip_homework_by_user homework
  67. filename = ((homework.user.user_extensions.nil? || homework.user.user_extensions.student_id.nil?) ? "" : homework.user.user_extensions.student_id) +
  68. "_" + homework.user.show_name +
  69. "_" + homework.name + ".zip"
  70. send_file zipfile.file_path, :filename => filename_for_content_disposition(filename), :type => detect_content_type(zipfile.file_path) if(zipfile)
  71. else
  72. render file: 'public/no_file_found.html'
  73. end
  74. else
  75. render file: 'public/file_not_found.html'
  76. end
  77. else
  78. render_403
  79. end
  80. #rescue => e
  81. # render file: 'public/file_not_found.html'
  82. end
  83. private
  84. #通过作业Id找到项目(课程)
  85. def find_project_by_bid_id
  86. obj_class = params[:obj_class]
  87. obj_id = params[:obj_id]
  88. obj = obj_class.constantize.find(obj_id)
  89. case obj.class.to_s.to_sym
  90. when :Bid
  91. @project = obj.courses[0]
  92. end
  93. end
  94. def zip_bid(bid)
  95. # Todo: User Access Controll
  96. bid_homework_path = []
  97. digests = []
  98. bid.homeworks.each do |homeattach|
  99. unless homeattach.attachments.empty?
  100. out_file = zip_homework_by_user(homeattach)
  101. bid_homework_path << out_file.file_path
  102. digests << out_file.file_digest
  103. end
  104. end
  105. homework_id = bid.id
  106. user_id = bid.author_id
  107. out_file = find_or_pack(homework_id, user_id, digests.sort){
  108. zipping("#{Time.now.to_i}_#{bid.name}.zip",
  109. bid_homework_path, OUTPUT_FOLDER)
  110. }
  111. [{files:[out_file.file_path], count: 1, index: 1,
  112. real_file: out_file.file_path,
  113. file: File.basename(out_file.file_path),
  114. base64file: encode64(File.basename(out_file.file_path)),
  115. size:(out_file.pack_size / 1024.0 / 1024.0).round(2)
  116. }]
  117. end
  118. def encode64(str)
  119. Base64.urlsafe_encode64(str)
  120. end
  121. def decode64(str)
  122. Base64.urlsafe_decode64(str)
  123. end
  124. def zip_homework_common homework_common
  125. bid_homework_path = []
  126. digests = []
  127. homework_common.student_works.each do |work|
  128. unless work.attachments.empty?
  129. out_file = zip_student_work_by_user(work)
  130. bid_homework_path << out_file.file_path
  131. digests << out_file.file_digest
  132. end
  133. end
  134. homework_id = homework_common.id
  135. user_id = homework_common.user_id
  136. out_file = find_or_pack(homework_id, user_id, digests.sort){
  137. zipping("#{Time.now.to_i}_#{homework_common.name}.zip",
  138. bid_homework_path, OUTPUT_FOLDER)
  139. }
  140. [{files:[out_file.file_path], count: 1, index: 1,
  141. real_file: out_file.file_path,
  142. file: File.basename(out_file.file_path),
  143. base64file: encode64(File.basename(out_file.file_path)),
  144. size:(out_file.pack_size / 1024.0 / 1024.0).round(2)
  145. }]
  146. end
  147. def zip_homework_by_user(homework_attach)
  148. homeworks_attach_path = []
  149. not_exist_file = []
  150. # 需要将所有homework.attachments遍历加入zip
  151. digests = []
  152. homework_attach.attachments.each do |attach|
  153. if File.exist?(attach.diskfile)
  154. homeworks_attach_path << attach.diskfile
  155. digests << attach.digest
  156. else
  157. not_exist_file << attach.filename
  158. digests << 'not_exist_file'
  159. end
  160. end
  161. out_file = find_or_pack(homework_attach.bid_id, homework_attach.user_id, digests.sort){
  162. zipping("#{homework_attach.user.show_name}_#{((homework_attach.user.user_extensions.nil? || homework_attach.user.user_extensions.student_id.nil?) ? "" : homework_attach.user.user_extensions.student_id)}_#{Time.now.to_i.to_s}.zip",
  163. homeworks_attach_path, OUTPUT_FOLDER, true, not_exist_file)
  164. }
  165. end
  166. def make_zip_name(work)
  167. "#{work.user.show_name}_#{((work.user.user_extensions.nil? || work.user.user_extensions.student_id.nil?) ? "" : work.user.user_extensions.student_id)}_#{Time.now.to_i.to_s}"
  168. end
  169. def zip_student_work_by_user(work)
  170. homeworks_attach_path = []
  171. not_exist_file = []
  172. # 需要将所有homework.attachments遍历加入zip
  173. digests = []
  174. work.attachments.each do |attach|
  175. if File.exist?(attach.diskfile)
  176. homeworks_attach_path << attach.diskfile
  177. digests << attach.digest
  178. else
  179. not_exist_file << attach.filename
  180. digests << 'not_exist_file'
  181. end
  182. end
  183. #单个文件的话,不需要压缩,只改名
  184. out_file = nil
  185. if homeworks_attach_path.size == 1
  186. out_file = find_or_pack(work.homework_common_id, work.user_id, digests.sort){
  187. des_path = "#{OUTPUT_FOLDER}/#{make_zip_name(work)}_#{File.basename(homeworks_attach_path.first)}"
  188. FileUtils.cp homeworks_attach_path.first, des_path
  189. des_path
  190. }
  191. else
  192. out_file = find_or_pack(work.homework_common_id, work.user_id, digests.sort){
  193. zipping("#{make_zip_name(work)}.zip",
  194. homeworks_attach_path, OUTPUT_FOLDER, true, not_exist_file)
  195. }
  196. end
  197. out_file
  198. end
  199. def find_or_pack(homework_id, user_id, digests)
  200. raise "please given a pack block" unless block_given?
  201. out_file = ZipPack.packed?(homework_id, user_id, digests.sort)
  202. unless out_file && out_file.file_valid?
  203. file = yield
  204. ZipPack.where(homework_id: homework_id,
  205. user_id: user_id).delete_all
  206. out_file = ZipPack.create(homework_id: homework_id,
  207. user_id: user_id,
  208. file_digest: Trustie::Utils.digest(file),
  209. file_path: file,
  210. pack_size: File.size(file),
  211. file_digests: digests.join(',')
  212. )
  213. else
  214. out_file.pack_times = out_file.pack_times + 1
  215. out_file.save
  216. end
  217. out_file
  218. end
  219. def zipping(zip_name_refer, files_paths, output_path, is_attachment=false, not_exist_file=[])
  220. rename_zipfile = zip_name_refer ||= "#{Time.now.to_i.to_s}.zip"
  221. # 文件名过长
  222. if rename_zipfile.size > MAX_PATH
  223. rename_zipfile = rename_zipfile[0,rename_zipfile.size-4][0,MAX_PATH-4] + rename_zipfile[-4,4]
  224. end
  225. zipfile_name = "#{output_path}/#{rename_zipfile}"
  226. Dir.mkdir(File.dirname(zipfile_name)) unless File.exist?(File.dirname(zipfile_name))
  227. Zip::File.open(zipfile_name, Zip::File::CREATE) do |zipfile|
  228. files_paths.each do |filename|
  229. rename_file = File.basename(filename)
  230. rename_file = filename_to_real( File.basename(filename)) if is_attachment
  231. begin
  232. zipfile.add(rename_file, filename)
  233. rescue Exception => e
  234. zipfile.get_output_stream('FILE_NOTICE.txt'){|os| os.write l(:label_file_exist)}
  235. next
  236. end
  237. end
  238. unless not_exist_file.empty?
  239. zipfile.get_output_stream('FILE_LOST.txt'){|os| os.write l(:label_file_lost) + not_exist_file.join(',').to_s}
  240. end
  241. end
  242. zipfile_name
  243. end
  244. # 合理分配文件打包
  245. # 如果小于 pack_attachment_max_size, 则返回单个文件
  246. # 反之则切分为多个文件组返回
  247. def split_pack_files(files, pack_attachment_max_size)
  248. max_size = 0
  249. last_files = []
  250. ret_files = []
  251. files.each_with_index do |f,i|
  252. if (max_size += File.size(f)) > pack_attachment_max_size
  253. max_size = 0
  254. if last_files.empty? #如果单个文件超过大小,也将此文件作为一组
  255. ret_files << {files: [f], count: 1, index: ret_files.count+1}
  256. last_files.clear
  257. else
  258. ret_files << {files:last_files, count: last_files.count, index: ret_files.count+1}
  259. last_files.clear
  260. redo
  261. end
  262. else
  263. last_files << f
  264. end
  265. end
  266. ret_files << {files:last_files, count: last_files.count, index: ret_files.count+1} unless last_files.empty?
  267. ret_files
  268. end
  269. def detect_content_type(name)
  270. content_type = Redmine::MimeType.of(name)
  271. content_type.to_s
  272. end
  273. def filename_to_real(name)
  274. attach = Attachment.find_by_disk_filename(name)
  275. attach.filename
  276. end
  277. end

软件技术创新是当今国家整体创新能力的重要基础和发展引擎。近年来,大众参与的软件创新与创业活动已经成为网络时代软件开发和应用的新形态,正在快速改变着全球软件创新模式和软件产业格局。 ...