Skip to content

Instantly share code, notes, and snippets.

@boris317
Created September 10, 2012 20:57
Show Gist options
  • Save boris317/3693796 to your computer and use it in GitHub Desktop.
Save boris317/3693796 to your computer and use it in GitHub Desktop.
Stream a tar file with flask.
import os
from cStringIO import StringIO
import tarfile
from flask import Flask, Response
app = Flask(__name__)
def get_string_io_len(s):
pos = s.tell()
s.seek(0, os.SEEK_END)
length = s.tell()
s.seek(pos)
return length
class CrazyBuffer(object):
def __init__(self):
self._buffer = StringIO()
def read(self, nbytes=None):
pass
def write(self, data):
self._buffer.write(data)
def close(self):
pass
def tell(self):
return 0
def seek(self, offset, whence=None):
return 0
def get_value(self):
return self._buffer.getvalue()
def reset(self):
self._buffer.close()
self._buffer = StringIO()
def streamed_tar_response(files):
crazy_buffer = CrazyBuffer()
tar = tarfile.open("test.tar", "w", crazy_buffer)
for i, f in enumerate(files):
info = tarfile.TarInfo(name="File_%s.txt" % i)
#stringIO specific here
info.size = get_string_io_len(f)
tar.addfile(info, f)
yield crazy_buffer.get_value()
crazy_buffer.reset()
# Making shit up at this point in case there
# is someting in the buffer after the loop.
# Not sure if actually needed!
tar.close()
yield crazy_buffer.get_value()
@app.route("/tar", methods=["GET"])
def get_tar():
files = [
StringIO("I am file 1."),
StringIO("I am file 2.")
]
return Response(streamed_tar_response(files), mimetype="application/x-tar")
if __name__ == "__main__":
app.run()
@ioistired
Copy link

Terrible. This reads the entire tar file into memory and sends it all at once to the client. The only reason you call it streaming is cause there's a generator involved.

@boris317
Copy link
Author

boris317 commented Nov 9, 2019

¯_(ツ)_/¯

@ioistired
Copy link

Oh wait my bad. It's not as bad as I thought. As each file is added, it's read into memory and then sent to the client as a whole. Fine if all your files are small, but not what I'm looking for.

@Gu-f
Copy link

Gu-f commented Apr 3, 2023

Oh wait my bad. It's not as bad as I thought. As each file is added, it's read into memory and then sent to the client as a whole. Fine if all your files are small, but not what I'm looking for.

I had the same problem. What's your solution?

@ioistired
Copy link

ioistired commented Apr 3, 2023 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment