Upload small file to FastAPI enpoint but UploadFile content is empty - file-upload

I am trying to upload file (csv) to FastAPI POST endpoint.
This is the server code:
#app.post("/csv/file/preview")
async def post_csv_file_preview(file: UploadFile):
"""
:param file:
:return:
"""
contents = file.file.read()
print(contents)
But contents is empty if the file is small. If I increase the file content (add new lines in the csv file), without any others changes, it is working.
If I directly get the request body, the file content is returned normally.
print(await request.body())
The problem is only with my production server, not localally:
PYTHONPATH=/var/www/api/current /var/www/api/current/venv/bin/python /var/www/api/current/venv/bin/uvicorn main:app --reload --port=8004
I dont understand

Thanks to the comment from Chris, I solved my problem by adding the .seek() method before reading the file contents.
#app.post("/csv/file/preview")
def post_csv_file_preview(file: UploadFile):
"""
:param file:
:return:
"""
file.file.seek(0)
contents = file.file.read()
print(contents)

Related

I'm trying to use input to output to a filename

I'm trying to use input to variable to create a file using the input the filename
The only examples I've seen are print(input)
I'm new to Python but trying to write a functional program
thanks
This is nice beginning for you
def create_file():
fn = input('Enter file name: ').strip()
try:
file = open(fn, 'r')
except IOError:
file = open(fn, 'w')
In Python you can use the open() function to create a file (assuming it will be a text file).
The documentation for it is located here
Using your input variable to create the file, you could do it like so:
file = open(input, 'w+')
This will give you a file object which you can write lines to using the write() function.

Boto3: upload file from base64 to S3

How can I directly upload a base64 encoded file to S3 with boto3?
object = s3.Object(BUCKET_NAME,email+"/"+save_name)
object.put(Body=base64.b64decode(file))
I tried to upload the base64 encoded file like this, but then the file is broken. Directly uploading the string without the base64 decoding also doesn't work.
Is there anything similar to set_contents_from_string() from boto2?
I just fixed the problem and found out that the way of uploading was correct, but the base64 string was incorrect because it still contained the prefix data:image/jpeg;base64, - removing that prefix solved the problem.
If you read the documentation thoughtfully on Object.put, you will see this
response = object.put(
ACL='private'......,
Body=b'bytes'|file,
.....,
Body only accept file object or bytes, any other type will failed. base64.b64decode doesn't read file object automatically, you must read the data into the decode module.
# FIX
object.put(Body=base64.b64decode(file.read()))
As reminder, always post the stacktrace.

Write in memory object to S3 via boto3

I am attempting to write files directly to S3 without creating a local file which is then uploaded.
I am using cStringIO to generate a file in memory, but I am having trouble figuring out the proper way to upload it in boto3.
def writetos3(sourcedata, filename, folderpath):
s3 = boto3.resource('s3')
data = open(sourcedata, 'rb')
s3.Bucket('bucketname').put_object(Key= folderpath + "/" + filename, Body=data)
Above is the standard boto3 method that I was using previously with the local file, it does not work without a local file, I get the following error: coercing to Unicode: need string or buffer, cStringIO.StringO found
.
Because the in memory file (I believe) is already considered open, I tried changing it to the code below, but it still does not work, no error is given the script simply hangs on the last line of the method.
def writetos3(sourcedata, filename, folderpath):
s3 = boto3.resource('s3')
s3.Bucket('bucketname').put_object(Key= folderpath + "/" + filename, Body=sourcedata)
Just for more info, the value I am attempting to write looks like this
(cStringIO.StringO object at 0x045DC540)
Does anyone have an idea of what I am doing wrong here?
It looks like you want this:
data = open(sourcedata, 'rb').decode()
It defaults to utf8. Also, I encourage you to run your code under python3, and to use appropriate language tags for your question.

How to upload image through JMeter?

I have a website which needs to upload multiple images at a time. So I want to know what is the process of posting image file through JMeter?
You'll need the following:
In HTTP Request Sampler:
Select "POST" method from drop-down.
Check "Use multipart/form-data for POST" box
Provide correct input name, MIME type and path for the file to be uploaded.
See Upload and Download Scenarios with Apache JMeter guide for more details.
If you need to upload multiple images best option is to go for a CSV Data Set Config element in Jmeter.
First, add the full path of the images you want to upload comma separately in a file (.csv) as below.
eg: D:\User\Images\img1.png,D:\User\Images\img2.png
Then, add a CSV Data Set Config element most preferably to the top of the script
Next, configure the below elements in the CSV Data Set Config element
Filename: full path to the csv file
Variable names: “column name” in the csv file if you have added one or any variable name if you don't have a column name (eg: images)
Note: Make sure to change the delimiter and other optional parameters as required.
Finally, in a HTTP Request you can use the parameter ${images} to call the images. The CSV Data Set Config element will read the image names from the CSV file and set them in the variable called "images".
Refer the below guide for more information.
https://www.blazemeter.com/blog/how-test-image-upload-functionality-jmeter

No such file or directory when opening file in memory with ZipRuby Zip::File

I'm consuming an api that replies with a zip file in the contents of the body of the http response. I'm able to unzip the file and write each file to disk using the example at the zip-ruby wiki (https://bitbucket.org/winebarrel/zip-ruby/wiki/Home):
Zip::Archive.open('filename.zip') do |ar| # except I'm opening from a string in memory
ar.each do |zf|
if zf.directory?
FileUtils.mkdir_p(zf.name)
else
dirname = File.dirname(zf.name)
FileUtils.mkdir_p(dirname) unless File.exist?(dirname)
open(zf.name, 'wb') do |f|
f << zf.read
end
end
end
end
However, I don't want to write the files to disk. Instead, I want create an active record object, and set a paperclip file attachment:
asset = Asset.create(:name => zf.name)
asset.file = open(zf.name, 'r')
asset.save
What's odd is the open statement in the first example that writes the file to disk works consistently. However, when I want to just open the zf (Zip::File) as a generic File in memory, I will sometimes get:
*** Errno::ENOENT Exception: No such file or directory - assets/somefilename.png
How can I assign the Zip::File zipruby creates to the paperclip file without getting this error?