return self._get_upload("SELECT * FROM uploads \
WHERE uuid = %s AND expires_at > CURRENT_TIMESTAMP", uuid)
- def create(self, filename, f, builder=None, user=None):
+ def allocate_file(self):
+ """
+ Returns a file handle which can be used to write temporary data to.
+ """
+ return tempfile.NamedTemporaryFile(dir=UPLOADS_DIR, delete=False)
+
+ def create(self, filename, path, size=None, builder=None, user=None):
# Check if either builder or user are set
if not builder and not user:
raise ValueError("builder or user must be set")
- # Reset f
- f.seek(0)
-
- # Create a new temporary file
- t = tempfile.NamedTemporaryFile(dir=UPLOADS_DIR, delete=False)
-
- # Copy all content from f
- shutil.copyfileobj(f, t)
+ # Fetch size if none given
+ if size is None:
+ size = os.path.getsize(path)
upload = self._get_upload("""
INSERT INTO
)
RETURNING *""",
filename,
- t.name,
- t.tell(),
- builder.id if builder else None,
- user.id if user else None,
+ path,
+ size,
+ builder,
+ user,
)
- # Close the temporary file
- t.close()
-
# Return the newly created upload object
return upload
self.bytes_read = 0
# Allocate a temporary file
- self.f = tempfile.SpooledTemporaryFile(max_size=10485760)
+ self.f = self.backend.uploads.allocate_file()
self.h, self.hexdigest = self._setup_digest()
# Write payload
self.f.write(data)
- def put(self):
+ async def put(self):
"""
Called after the entire file has been received
"""
with self.db.transaction():
upload = self.backend.uploads.create(
self.filename,
- self.f,
+ self.f.name,
builder=self.builder,
user=self.user,
)
+ # Free the temporary file (to prevent cleanup)
+ self.f = None
+
# Send the ID of the upload back to the client
self.finish({
"id" : upload.uuid,
return h, hexdigest
+ def on_connection_close(self):
+ """
+ Called when a connection was unexpectedly closed
+ """
+ # Try deleting the file
+ if self.f:
+ log.debug("Deleting temporary file %s" % self.f.name)
+ os.unlink(self.f.name)
+
# Builds