How to check if a file is csv or not? - django

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.

Related

How to pass inMemoryUploadedFile into an api

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'),
})

Flask does not list outputs of multiple files

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.

django: how to correctly specify output-download file-type (in this case mp3)?

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')

How to access file after upload in Django?

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.

Django (audio) File Validation

I'm experimenting with a site that will allow users to upload audio files. I've read every doc that I can get my hands on but can't find much about validating files.
Total newb here (never done any file validation of any kind before) and trying to figure this out. Can someone hold my hand and tell me what I need to know?
As always, thank you in advance.
You want to validate the file before it gets written to disk. When you upload a file, the form gets validated then the uploaded file gets passed to a handler/method that deals with the actual writing to the disk on your server. So in between these two operations, you want to perform some custom validation to make sure it's a valid audio file
You could:
check if the the file is less then a certain size (good practice)
then check if the submitted file has a certain content type (i.e. an audio file)
this is pretty useless as someone could easily spoof it
then check that the file ends in a certain extension (or extensions)
this is also pretty useless
try read the file and see if it's actually audio
(I haven't tested this code)
models.py
class UserSong(models.Model):
title = models.CharField(max_length=100)
audio_file = models.FileField()
forms.py
class UserSongForm(forms.ModelForm):
# Add some custom validation to our file field
def clean_audio_file(self):
file = self.cleaned_data.get('audio_file',False):
if file:
if file._size > 4*1024*1024:
raise ValidationError("Audio file too large ( > 4mb )")
if not file.content-type in ["audio/mpeg","audio/..."]:
raise ValidationError("Content-Type is not mpeg")
if not os.path.splitext(file.name)[1] in [".mp3",".wav" ...]:
raise ValidationError("Doesn't have proper extension")
# Here we need to now to read the file and see if it's actually
# a valid audio file. I don't know what the best library is to
# to do this
if not some_lib.is_audio(file.content):
raise ValidationError("Not a valid audio file")
return file
else:
raise ValidationError("Couldn't read uploaded file")
views.py
from utils import handle_uploaded_file
def upload_file(request):
if request.method == 'POST':
form = UserSongForm(request.POST, request.FILES)
if form.is_valid():
# If we are here, the above file validation has completed
# so we can now write the file to disk
handle_uploaded_file(request.FILES['file'])
return HttpResponseRedirect('/success/url/')
else:
form = UploadFileForm()
return render_to_response('upload.html', {'form': form})
utils.py
# from django's docs
def handle_uploaded_file(f):
ext = os.path.splitext(f.name)[1]
destination = open('some/file/name%s'%(ext), 'wb+')
for chunk in f.chunks():
destination.write(chunk)
destination.close()
https://docs.djangoproject.com/en/dev/topics/http/file-uploads/#file-uploads
https://docs.djangoproject.com/en/dev/ref/forms/fields/#filefield
https://docs.djangoproject.com/en/dev/ref/files/file/#django.core.files.File