I am using Flask to render some analysis based on taking image as an input using Flask reuploaded and werkzeug. Though the input accepts multiple images, the output is rendered of only one image instead of all the images that were uploaded.
There is no error message that I am receiving.
HTML code:
<form method="POST" action="" enctype="multipart/form-data"><p>
<input type="file" name="file" multiple
accept="image/x-png,image/gif,image/jpeg">
<input type="submit" value="Upload">
Post request
#app.route('/', methods=['POST'])
def upload_image():
if request.method == 'POST':
# checks whether or not the post request has the file part
if 'file' not in request.files:
flash('No file part')
return redirect(request.url)
file = request.files['file']
# if user does not select file, browser also
# submit a empty part without filename
if file.filename == '':
flash('No file selected for uploading')
return redirect(request.url)
files = request.files.getlist('files[]')
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(os.getcwd() +
UPLOAD_INPUT_IMAGES_FOLDER, file.filename))
flash('File successfully uploaded')
# calls the ocr_processing function to perform text extraction
extracted_text = ocr_processing(file)
print(extracted_text)
match = extracted_text.lower()
df = pd.read_csv("/Users/ri/Desktop/DPL/DPL.csv")
for row in df.Pattern_String:
result = ratio(row, match)
print(result)
if result >= 10:
else:
return render_template('uploads/results.html',
msg='Processed successfully!',
match=match,
img_src=UPLOAD_INPUT_IMAGES_FOLDER + file.filename)
else:
flash('Allowed file types are txt, pdf, png, jpg, jpeg, gif')
return redirect(request.url)
You define files = request.files.getlist('files[]'), but then you do not use it.
You need to iterate over all uploaded files, ie you need e.g. a for loop.
I would start renaming the misleading input name file to files and then start over.
Related
I want to pass user uploaded images into an api from my view
I have this form which submits a file into view
<form action="http://127.0.0.1:8000/handler/" method="POST" enctype="multipart/form-data">
<input type="file" name="file">
<input type="submit">
</form>
I want to again send this file into an api but I can't do it directly, I think i must convert the file into string and pass to the api. Anybody have any idea on how to do it
#csrf_exempt
def handler(request):
if request.method == 'POST':
file = request.FILES['file']
res = requests.post('http://192.168.1.68:8000/endpoint/',{})
This is for the future me or someone who might have the same issue.
Make sure to respect the correct headers while using requests lib and sending files.
I follow the code and nothing work because we use remote models, so we have constructors and the headers dict was setting another 'content type'.
So if you need to set the token for the api call, you can use it like this:
getFile = request.FILES['form-data-name'].file.getvalue()
file = {'form-data-name': getFile,} #The other api get this field
self.response = requests.post(
f'{self.service}/resource/{pk}/action/',
headers={'Authorization': f'Bearer {self.token}'},
files=file
)
If have to convert the file into string, you can use file.read().
But this is not recommended,if the uploaded file is huge it can overwhelm your system if you try to read it into memory.
For better practice, you should use TemporaryUploadedFile and open a stream to send any content:
# file handle by "TemporaryUploadedFile" already
file = request.FILES['file']
res = requests.post('http://192.168.1.68:8000/endpoint/', {
"file": open(file.temporary_file_path(), 'rb'),
})
I have a django views function that converts csv into another delimiter format. But, I just want to convert csv file and reject other files.
def index(request):
csv_form = ''
if request.method == 'POST':
csv_form = CsvForm(request.POST, request.FILES)
if csv_form.is_valid():
csv_file = TextIOWrapper(request.FILES['csv_file'].file, encoding='ascii', errors='replace')
#other actions
I cannot use the below code because this works with only binary files, but the csv module wants to have text-mode files instead. Any alternatives to proceed with only csv files.
if not csv_file.name.endswith('.csv'):
messages.error(request, 'THIS IS NOT A CSV FILE')
Depending on how secure this needs to be. The easiest step is simply to limit the extension type on the upload HTML field.
<input type="file" accept=".csv" />
Obviously, anyone could just name the extension .csv to circumnavigate but that would be the case with any solution that is just checking extensions.
You can check if there are any commas, and if there are any words between them.
I'm running into an unexpected 500 Internal Server Error when I don't believe I've changed the relevant code. I've tried reverting to a previous version of the same code (when it was working) without issue.
It is only occuring when trying to upload a file and doesn't return any debug messages that I've been able to capture.
Code below:
HTML code
<form method="post" action="/picture" enctype="multipart/form-data">
<input type="file" name="file" autocomplete="off" required>
<input type="submit" value="Upload!">
</form>
Flask code
# Upload File Configuration
ALLOWED_EXTENSIONS = set(['png', 'jpg', 'jpeg', 'gif'])
UPLOAD_FOLDER = 'static/uploads/'
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
# Set Profile Photo
#app.route('/picture', methods=["POST"])
#login_required
def upload_image():
if request.method == "POST":
if 'file' not in request.files:
flash('No file part')
return redirect("/profile")
file = request.files['file']
if file.filename == '':
flash('No image selected for uploading')
return redirect(request.url)
if file and allowed_file(file.filename):
filename = (str(session["user_id"]) + '_' + secure_filename(file.filename))
rows = db.execute("SELECT profile_photo FROM users WHERE id=:id", id=session["user_id"])
#if user already has profile picture
if rows[0]["profile_photo"] != None:
os.remove(os.path.join(app.config['UPLOAD_FOLDER'], rows[0]["profile_photo"]))
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
db.execute("UPDATE users SET profile_photo = :filelocation WHERE id = :user_id", user_id=session["user_id"], filelocation=filename)
rows = db.execute("SELECT firstname, lastname, email, postcode, bio, hobbies, profile_photo FROM users WHERE id = :id",
id=session["user_id"])
filename = rows[0]["profile_photo"]
flash('Profile picture updated!')
return render_template("profile.html", rows=rows, filename=filename)
else:
flash('Photo not updated - allowed image types are -> png, jpg, jpeg, gif')
return redirect("/profile")
It was working before so I'm surprised at the sudden reversion. I'm new to flask so any pointers or tips would be greatly appreciated!
I have a simple django platform where I can upload text files. Ultimately I want to return a downloadable mp3 audio file made from the text in the uploaded file. My problem currently is that I cannot seem to correctly specify the type of file that the website outputs for download.
I then tried to make the downloadable output of the website an mp3 file:
views.py (code adapted from https://github.com/sibtc/simple-file-upload)
def simple_upload(request):
if request.method == 'POST' and request.FILES['myfile']:
myfile = request.FILES['myfile']
print(str(request.FILES['myfile']))
x=str(myfile.read())
tts = gTTS(text=x, lang='en')
response=HttpResponse(tts.save("result.mp3"),content_type='mp3')
response['Content-Disposition'] = 'attachment;filename=result.mp3'
return response
return render(request, 'core/simple_upload.html')
Upon pressing the upload button, the text-to-speech conversion is successful but the content_type of the response is not definable as 'mp3'. The file that results from the download is result.mp3.txt and it contains 'None'.
Can you try to prepare your response using the sample code below?
I've managed to return CSV files correctly this way so it might help you too.
Here it is:
HttpResponse(content_type='text/plain') # Plain text file type
response['Content-Disposition'] = 'attachment; filename="attachment.txt"' # Plain text file extension
response.write("Hello, this is the file contents.")
return response
There are two problems I can see here. The first is that tts.save() returns None, and that is getting passed directly to the HttpResponse. Secondly, the content_type is set to mp3 and ought to be set to audio/mp3.
After calling tts.save(), open the mp3 and pass the file handle to the HttpResponse, and then also set the content_type correctly - for example:
def simple_upload(request):
if request.method == 'POST' and request.FILES['myfile']:
...
tts.save("result.mp3")
response=HttpResponse(open("result.mp3", "rb"), content_type='audio/mp3')
I'm working on a web. User can upload a file. This file is in docx format. After he uploads a file and choose which languages he wants to translate the file to, I want to redirect him to another page, where he can see prices for translations. The prices depends on particular language and number of characters in the docx file.
I can't figure out how to handle the file uploaded. I have a function which get's path to file and returns a number of characters. After uploading file and click on submit, I want to call this function so I can render new page with estimated prices.
I've read that I can call temporary_file_path on request.FILES['file'] but it raises
'InMemoryUploadedFile' object has no attribute 'temporary_file_path'
I want to find out how many characters uploaded file contains and send it in a request to another view - /order-estimation.
VIEW:
def create_order(request):
LanguageLevelFormSet = formset_factory(LanguageLevelForm, extra=5, max_num=5)
language_level_formset = LanguageLevelFormSet(request.POST or None)
job_creation_form = JobCreationForm(request.POST or None, request.FILES or None)
context = {'job_creation_form': job_creation_form,
'formset': language_level_formset}
if request.method == 'POST':
if job_creation_form.is_valid() and language_level_formset.is_valid():
cleaned_data_job_creation_form = job_creation_form.cleaned_data
cleaned_data_language_level_formset = language_level_formset.cleaned_data
for language_level_form in [d for d in cleaned_data_language_level_formset if d]:
language = language_level_form['language']
level = language_level_form['level']
Job.objects.create(
customer=request.user,
text_to_translate=cleaned_data_job_creation_form['text_to_translate'],
file=cleaned_data_job_creation_form['file'],
short_description=cleaned_data_job_creation_form['short_description'],
notes=cleaned_data_job_creation_form['notes'],
language_from=cleaned_data_job_creation_form['language_from'],
language_to=language,
level=level,
)
path = request.FILES['file'].temporary_file_path
utilities.docx_get_characters_number(path) # THIS NOT WORKS
return HttpResponseRedirect('/order-estimation')
else:
return render(request, 'auth/jobs/create-job.html', context=context)
return render(request, 'auth/jobs/create-job.html', context=context)
The InMemoryUploadedFile does not provide temporary_file_path. The content lives 'in memory' - as the class name implies.
By default Django uses InMemoryUploadedFile for files up to 2.5MB size, larger files use TemporaryFileUploadHandler. where the later provides the temporary_file_path method in question. Django Documentation
So an easy way would be to change your settings for FILE_UPLOAD_HANDLERS to always use TemporaryFileUploadHandler:
FILE_UPLOAD_HANDLERS = [
'django.core.files.uploadhandler.TemporaryFileUploadHandler',
]
Just keep in mind that this is not the most efficient way when you have a site with a lot of concurrent small upload requests.