1

I am working on a api end-point that will be available for public use using Python's Fast API framework. It is already done and working but the way it works is I will create it, then save to the local directory of the server then read that file and return a csv file as a response to the user.

My question is, how do I just return the csv file directly to the user without saving it in the server's directory. My code is like this right now

def export_client_invoice(client_id):

    invoice_doc = client_docs_db.view("client_invoice/by_client_id", key=int(client_id), include_docs=True)

    data = ["value %d" % i for i in range(1,4)]

    with open("./file.csv", 'w', newline='') as myfile:
    wr = csv.writer(myfile, quoting=csv.QUOTE_ALL)
    wr.writerow(data)

    file_like = open("./file.csv", mode="rb")
    response = StreamingResponse(file_like, media_type="text/csv")
    response.headers["Content-Disposition"] = "attachment; filename=export.csv"
    
return response
jackhammer013
  • 2,295
  • 11
  • 45
  • 95
  • I'm getting `TypeError: 'StreamWriter' object is not an iterator`. Did you get a working solution? Thanks – Stealth Rabbi Aug 09 '22 at 15:55
  • Related answers can be found [here](https://stackoverflow.com/a/74588435/17865804), as well as [here](https://stackoverflow.com/a/71205127/17865804) and [here](https://stackoverflow.com/a/70655118/17865804). – Chris Jan 05 '23 at 09:25

2 Answers2

1

I cannot test it with fastapi, so you may have to adopt this a bit to make it work in your context.

from io import BytesIO
import csv
import codecs

data = ['value %d' % i for i in range(1,4)]

StreamWriter = codecs.getwriter('utf-8')
file_like = StreamWriter(BytesIO())

wr = csv.writer(file_like, quoting=csv.QUOTE_ALL)
wr.writerow(data)

print(file_like.getvalue())
# b'"value 1","value 2","value 3"\r\n'

response = StreamingResponse(file_like, media_type="text/csv")
Durtal
  • 1,063
  • 3
  • 11
  • I'm getting `TypeError: 'StreamWriter' object is not an iterator` – Stealth Rabbi Aug 09 '22 at 15:29
  • @StealthRabbi You should report the code that produces the error. Most probably in a new thread. – Durtal Aug 09 '22 at 16:29
  • It's the line that is creating the `StreamingResponse`. Not sure what you mean by "new thread". – Stealth Rabbi Aug 09 '22 at 16:56
  • @StealthRabbi Ask a new question including a [minimal, reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) – Durtal Aug 10 '22 at 07:20
  • My comment is directly about the answer that you posted here, so I'm not sure why I'd ask a new question about someone else's answer. – Stealth Rabbi Aug 10 '22 at 14:19
  • Dear @StealthRabbi, please understand my answer in the context of the question. I showed how it may work and clearly indicated, that I didn't test my code with `fastapi`. This seemed appropriate because OP didn't declare what they are going to do with the response object. Now, even after installing `fastapi`, my code doesn't produce the error you report. I get a valid StreamingResponse-object. Does it what you want? I don't know! Was it created without using a temp file as OP asked for? Yes, it was. So I am not sure what to make out of your comments. – Durtal Aug 10 '22 at 23:26
0

@jackhammer013, You can using this code to return csv file with FastAPI

from fastapi.responses import StreamingResponse
... 
    return StreamingResponse(iter([file_like.getvalue()]),
                                             status_code=status.HTTP_200_OK,
                                             headers={
                                                 "Content-Disposition": f"attachment; filename=test.csv"
                                             },
                                             media_type="text/csv")
Tho Bui Ngoc
  • 763
  • 1
  • 11
  • 36