Added files module, with for now, a focus on upload files facility.
Contribution from Fabian Murer, as part of an ETH student project. Supervised, refactorized and merged by Jocelyn Fiat. Signed-off-by: Fabian Murer <fmurer@student.ethz.ch> Signed-off-by: Jocelyn Fiat <git@djoce.net>
This commit is contained in:
272
modules/files/cms_files_api.e
Normal file
272
modules/files/cms_files_api.e
Normal file
@@ -0,0 +1,272 @@
|
||||
note
|
||||
description: "API to manage files."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
CMS_FILES_API
|
||||
|
||||
inherit
|
||||
CMS_MODULE_API
|
||||
|
||||
REFACTORING_HELPER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature -- Access : path
|
||||
|
||||
uploads_relative_path: PATH
|
||||
-- Path relative to `{CMS_API}.files_location'.
|
||||
do
|
||||
create Result.make_from_string (uploads_directory_name)
|
||||
end
|
||||
|
||||
uploads_directory: PATH
|
||||
do
|
||||
Result := cms_api.files_location.extended (uploads_directory_name)
|
||||
end
|
||||
|
||||
uploaded_file_path (f: READABLE_STRING_GENERAL): PATH
|
||||
do
|
||||
Result := uploads_directory.extended (f)
|
||||
end
|
||||
|
||||
thumbnail_directory: PATH
|
||||
do
|
||||
Result := uploads_directory.extended (thumbnail_directory_name)
|
||||
end
|
||||
|
||||
feature {CMS_FILES_MODULE} -- Access : metadata path
|
||||
|
||||
metadata_path (f: READABLE_STRING_GENERAL): PATH
|
||||
do
|
||||
Result := metadata_directory.extended (f).appended_with_extension ("cms-metadata")
|
||||
end
|
||||
|
||||
metadata_directory: PATH
|
||||
do
|
||||
Result := uploads_directory.extended (metadata_directory_name)
|
||||
end
|
||||
|
||||
feature -- Access : links
|
||||
|
||||
file_link (f: CMS_FILE): CMS_LOCAL_LINK
|
||||
local
|
||||
s: STRING
|
||||
do
|
||||
s := "files"
|
||||
across
|
||||
f.relative_path.components as ic
|
||||
loop
|
||||
s.append_character ('/')
|
||||
s.append (percent_encoded (ic.item.name))
|
||||
end
|
||||
create Result.make (f.filename, s)
|
||||
end
|
||||
|
||||
feature {NONE} -- Constants
|
||||
|
||||
uploads_directory_name: STRING = "uploads"
|
||||
|
||||
metadata_directory_name: STRING = ".metadata"
|
||||
|
||||
thumbnail_directory_name: STRING = ".thumbnails"
|
||||
|
||||
feature -- Factory
|
||||
|
||||
new_file (a_relative_path: PATH): CMS_FILE
|
||||
-- New CMS_FILE for path `a_relative_path' relative to `files' directory.
|
||||
do
|
||||
create Result.make (a_relative_path, cms_api)
|
||||
end
|
||||
|
||||
new_uploads_file (p: PATH): CMS_FILE
|
||||
-- New uploaded path from `p' relative to `uploads_directory'.
|
||||
do
|
||||
create Result.make (uploads_relative_path.extended_path (p), cms_api)
|
||||
end
|
||||
|
||||
feature -- Storage
|
||||
|
||||
delete_file (fn: READABLE_STRING_GENERAL)
|
||||
-- Delete file at `fn'.
|
||||
local
|
||||
p: PATH
|
||||
do
|
||||
error_handler.reset
|
||||
p := uploaded_file_path (fn)
|
||||
safe_delete (p)
|
||||
if not has_error then
|
||||
p := metadata_path (fn)
|
||||
safe_delete (p)
|
||||
end
|
||||
end
|
||||
|
||||
save_uploaded_file (uf: CMS_UPLOADED_FILE)
|
||||
local
|
||||
p: PATH
|
||||
ut: FILE_UTILITIES
|
||||
stored: BOOLEAN
|
||||
original_name: STRING_32
|
||||
n: INTEGER_32
|
||||
finished: BOOLEAN
|
||||
do
|
||||
reset_error
|
||||
create original_name.make_from_string (uf.filename)
|
||||
|
||||
p := uf.location
|
||||
if not p.is_absolute then
|
||||
p := uploads_directory.extended_path (p)
|
||||
end
|
||||
|
||||
if ut.file_path_exists (p) then
|
||||
|
||||
from
|
||||
n := 1
|
||||
until
|
||||
finished
|
||||
loop
|
||||
if ut.file_path_exists (p) then
|
||||
uf.set_new_location_with_number (n)
|
||||
p := uf.location
|
||||
if p.is_absolute then
|
||||
else
|
||||
p := uploads_directory.extended_path (p)
|
||||
end
|
||||
n := n + 1
|
||||
else
|
||||
finished := True
|
||||
end
|
||||
end
|
||||
stored := uf.move_to (p)
|
||||
else
|
||||
-- move file to path
|
||||
stored := uf.move_to (p)
|
||||
end
|
||||
|
||||
if stored then
|
||||
save_metadata_from_uploaded_file (uf, cms_api.user)
|
||||
else
|
||||
error_handler.add_custom_error (-1, "uploaded file storage failed", "Issue occurred when saving uploaded file!")
|
||||
end
|
||||
end
|
||||
|
||||
save_metadata_from_uploaded_file (a_uploaded_file: CMS_UPLOADED_FILE; u: detachable CMS_USER)
|
||||
local
|
||||
f: detachable RAW_FILE
|
||||
h_date: HTTP_DATE
|
||||
retried: BOOLEAN
|
||||
do
|
||||
if retried then
|
||||
-- FIXME: Report error?
|
||||
if f /= Void and then not f.is_closed then
|
||||
f.close
|
||||
end
|
||||
else
|
||||
-- create a file for metadata
|
||||
create f.make_with_path (metadata_path (a_uploaded_file.filename))
|
||||
|
||||
if f.exists then
|
||||
f.open_write
|
||||
else
|
||||
f.create_read_write
|
||||
end
|
||||
-- insert username
|
||||
if u /= Void then
|
||||
f.put_string (u.id.out)
|
||||
f.put_new_line
|
||||
-- f.put_string (utf.utf_32_string_to_utf_8_string_8 (u.name))
|
||||
-- f.put_new_line
|
||||
else
|
||||
f.put_new_line
|
||||
f.put_new_line
|
||||
end
|
||||
-- insert uploaded_time
|
||||
create h_date.make_now_utc
|
||||
f.put_string (h_date.timestamp.out)
|
||||
f.put_new_line
|
||||
|
||||
-- insert size of file
|
||||
f.put_string (a_uploaded_file.size.out)
|
||||
f.put_new_line
|
||||
|
||||
-- insert file type
|
||||
if attached a_uploaded_file.type as type then
|
||||
f.put_string (type.out)
|
||||
f.put_new_line
|
||||
end
|
||||
|
||||
f.close
|
||||
end
|
||||
rescue
|
||||
retried := True
|
||||
retry
|
||||
end
|
||||
|
||||
metadata (a_cms_file: CMS_FILE): detachable CMS_FILE_METADATA
|
||||
local
|
||||
f: RAW_FILE
|
||||
s: READABLE_STRING_8
|
||||
do
|
||||
if attached metadata_path (a_cms_file.filename) as p then
|
||||
create f.make_with_path (p)
|
||||
if f.exists and then f.is_access_readable then
|
||||
create Result.make_empty
|
||||
|
||||
f.open_read
|
||||
|
||||
f.read_line
|
||||
s := f.last_string
|
||||
if s.is_integer_64 then
|
||||
Result.set_user (cms_api.user_api.user_by_id (s.to_integer_64))
|
||||
else
|
||||
Result.set_user (cms_api.user_api.user_by_name (s))
|
||||
end
|
||||
|
||||
f.read_line
|
||||
s := f.last_string
|
||||
if s.is_integer_64 then
|
||||
Result.set_date ((create {HTTP_DATE}.make_from_timestamp (s.to_integer_64)).date_time)
|
||||
end
|
||||
|
||||
f.read_line
|
||||
s := f.last_string
|
||||
if s.is_integer_32 then
|
||||
Result.set_size (s.to_integer_32)
|
||||
else
|
||||
Result.set_size (-1)
|
||||
end
|
||||
|
||||
if not f.end_of_file then
|
||||
f.read_line
|
||||
Result.set_file_type (f.last_string)
|
||||
end
|
||||
f.close
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
safe_delete (p: PATH)
|
||||
-- Safe remove file at path `p'.
|
||||
local
|
||||
f: RAW_FILE
|
||||
retried: BOOLEAN
|
||||
do
|
||||
if retried then
|
||||
error_handler.add_custom_error (-1, "Can not delete file", {STRING_32} "Can not delete file %"" + p.name + "%"")
|
||||
else
|
||||
create f.make_with_path (p)
|
||||
if f.exists then
|
||||
f.delete
|
||||
else
|
||||
-- Not considered as failure.
|
||||
end
|
||||
end
|
||||
rescue
|
||||
retried := True
|
||||
retry
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
Reference in New Issue
Block a user