Show More
@@ -21,6 +21,7 b'' | |||
|
21 | 21 | import os |
|
22 | 22 | import time |
|
23 | 23 | import shutil |
|
24 | import hashlib | |
|
24 | 25 | |
|
25 | 26 | from rhodecode.lib.ext_json import json |
|
26 | 27 | from rhodecode.apps.file_store import utils |
@@ -63,6 +64,21 b' class LocalFileStorage(object):' | |||
|
63 | 64 | def _sub_store_from_filename(cls, filename): |
|
64 | 65 | return filename[:2] |
|
65 | 66 | |
|
67 | @classmethod | |
|
68 | def calculate_path_hash(cls, file_path): | |
|
69 | """ | |
|
70 | Efficient calculation of file_path sha256 sum | |
|
71 | ||
|
72 | :param file_path: | |
|
73 | :return: sha256sum | |
|
74 | """ | |
|
75 | digest = hashlib.sha256() | |
|
76 | with open(file_path, 'rb') as f: | |
|
77 | for chunk in iter(lambda: f.read(1024 * 100), b""): | |
|
78 | digest.update(chunk) | |
|
79 | ||
|
80 | return digest.hexdigest() | |
|
81 | ||
|
66 | 82 | def __init__(self, base_path, extension_groups=None): |
|
67 | 83 | |
|
68 | 84 | """ |
@@ -134,7 +150,7 b' class LocalFileStorage(object):' | |||
|
134 | 150 | return ext.lower() in extensions |
|
135 | 151 | |
|
136 | 152 | def save_file(self, file_obj, filename, directory=None, extensions=None, |
|
137 | metadata=None, **kwargs): | |
|
153 | extra_metadata=None, **kwargs): | |
|
138 | 154 | """ |
|
139 | 155 | Saves a file object to the uploads location. |
|
140 | 156 | Returns the resolved filename, i.e. the directory + |
@@ -144,8 +160,7 b' class LocalFileStorage(object):' | |||
|
144 | 160 | :param filename: original filename |
|
145 | 161 | :param directory: relative path of sub-directory |
|
146 | 162 | :param extensions: iterable of allowed extensions, if not default |
|
147 | :param metadata: JSON metadata to store next to the file with .meta suffix | |
|
148 | :returns: modified filename | |
|
163 | :param extra_metadata: extra JSON metadata to store next to the file with .meta suffix | |
|
149 | 164 | """ |
|
150 | 165 | |
|
151 | 166 | extensions = extensions or self.extensions |
@@ -163,23 +178,31 b' class LocalFileStorage(object):' | |||
|
163 | 178 | |
|
164 | 179 | filename = utils.uid_filename(filename) |
|
165 | 180 | |
|
181 | # resolve also produces special sub-dir for file optimized store | |
|
166 | 182 | filename, path = self.resolve_name(filename, dest_directory) |
|
183 | stored_file_dir = os.path.dirname(path) | |
|
167 | 184 | |
|
168 | 185 | file_obj.seek(0) |
|
169 | 186 | |
|
170 | 187 | with open(path, "wb") as dest: |
|
171 | 188 | shutil.copyfileobj(file_obj, dest) |
|
172 | 189 | |
|
173 |
|
|
|
190 | metadata = {} | |
|
191 | if extra_metadata: | |
|
192 | metadata = extra_metadata | |
|
193 | ||
|
174 | 194 |
|
|
195 | file_hash = self.calculate_path_hash(path) | |
|
196 | ||
|
175 | 197 |
|
|
176 |
|
|
|
198 | {"filename": filename, | |
|
199 | "size": size, | |
|
177 | 200 |
|
|
201 | "sha256": file_hash, | |
|
178 | 202 |
|
|
179 | 203 | |
|
180 | stored_file_path = os.path.dirname(path) | |
|
181 | 204 |
|
|
182 |
|
|
|
205 | with open(os.path.join(stored_file_dir, filename_meta), "wb") as dest_meta: | |
|
183 | 206 |
|
|
184 | 207 | |
|
185 | 208 | if directory: |
@@ -58,7 +58,7 b' class TestFileStoreViews(TestController)' | |||
|
58 | 58 | f.write(content) |
|
59 | 59 | |
|
60 | 60 | with open(filesystem_file, 'rb') as f: |
|
61 | fid, metadata = store.save_file(f, fid, metadata={'filename': fid}) | |
|
61 | fid, metadata = store.save_file(f, fid, extra_metadata={'filename': fid}) | |
|
62 | 62 | |
|
63 | 63 | else: |
|
64 | 64 | status = 404 |
@@ -63,13 +63,12 b' class FileStoreView(BaseAppView):' | |||
|
63 | 63 | filename = file_obj.filename |
|
64 | 64 | |
|
65 | 65 | metadata = { |
|
66 | 'filename': filename, | |
|
67 | 'size': '', # filled by save_file | |
|
68 | 66 | 'user_uploaded': {'username': self._rhodecode_user.username, |
|
69 | 67 | 'user_id': self._rhodecode_user.user_id, |
|
70 | 68 | 'ip': self._rhodecode_user.ip_addr}} |
|
71 | 69 | try: |
|
72 |
store_fid, metadata = self.storage.save_file( |
|
|
70 | store_fid, metadata = self.storage.save_file( | |
|
71 | file_obj.file, filename, extra_metadata=metadata) | |
|
73 | 72 | except FileNotAllowedException: |
|
74 | 73 | return {'store_fid': None, |
|
75 | 74 | 'access_path': None, |
General Comments 0
You need to be logged in to leave comments.
Login now