Python - simple requests file upload didn't work - python

i created a simple html upload file :
<!DOCTYPE html>
<html>
<body>
<form action="upload.php" method="post" enctype="multipart/form-data">
Select image to upload:
<input type="file" name="fileToUpload" id="fileToUpload">
<input type="submit" value="Upload Image" name="submit">
</form>
</body>
</html>
and a simple php upload file :
<?php
$target_dir = "";
$target_file = $target_dir . basename($_FILES["fileToUpload"]["name"]);
$uploadOk = 1;
$imageFileType = pathinfo($target_file,PATHINFO_EXTENSION);
if (move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $target_file)) {
echo "The file ". basename( $_FILES["fileToUpload"]["name"]). " has been uploaded.";
} else {
echo "Sorry, there was an error uploading your file.";
}
?>
i tested everything works perfectly
i want to submit a file upload with python using requests module so i created this :
import requests
url = 'http://localhost/upload/up.html'
files = [('images', ('1.jpg', open('1.jpg', 'rb'), 'image/jpg'))]
r = requests.post(url, files=files)
print r.text
it will return the html page code and the file uploading is failed , any solution ?

I think the issue is the name passed to post. Use fileToUpload rather than images like this:
files = [('fileToUpload', ('1.jpg', open('1.jpg', 'rb'), 'image/jpg'))]
r = requests.post(url, files=files)

Related

No return of result from FLASK call via AJAX in an alert notifcation on the web page

Basically I a comparing two texts one input is a pdf, another basic text.
I have created index html and within is another html for a bit clarity. using python FLASK feature.
All the code runs separately, all mentioned errors for invalid input run very fine together, its just the main result output, I presume I am messing up somehow in calling and executing the main function because all the alerts and file checks are working , and the logic inside of flask is working too.
My html file with ajax and form :
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
function submitForm() {
// Show the loading screen
document.getElementById("loading").style.display = "block";
// Get the input values
var JD = document.getElementById("JD").value;
var file = document.getElementById("FL").file[0];
// Check if a file has been selected and is a pdf
if (!file || file.type !== 'application/pdf') {
alert("Please select a valid PDF file");
return;
}
// Check if file size is less than 5 MB
if (file.size > 5000000) {
alert("File size should not exceed 5 MB");
return;
}
// Create a FormData object to send both the file and the jd to the API
var formData = new FormData($('#upload_form')[0]);
formData.append("FL", FL);
formData.append("JD", JD);
// Make the API call
$.ajax({
url: base_url + "api/Analyze",
type: "POST",
data: formData,
processData: false,
contentType: false,
success: function(result) {
// Hide the loading screen
document.getElementById("loading").style.display = "none";
alert(result);
},
error: function () {
// Hide the loading screen
document.getElementById("loading").style.display = "none";
// Display the error
alert("Error during API call");
}
});
}
</script>
</head>
<body>
<h2>Analysis</h2>
<form id="upload_form" enctype="multipart/form-data">
<p>
<label for="JD">Description:</label>
<textarea name = "JD" id="JD" rows="4" cols="50"></textarea>
</p>
<p>
<label for="FL">FILE:</label>
<input type="file" name="FL" id="FL" accept="application/pdf">
</p>
<p>
<input type="button" value="Submit" onclick="submitForm()">
</p>
</form>
<div id="loading" style="display: none;">Loading...</div>
And this is the app.py flask file -
from flask import Flask, render_template, redirect, request, jsonify
import fitz
import re
import sys
#(please ignore irrelevant imports)
app = Flask(__name__)
#app.route('/', methods=['GET'])
def index():
return render_template('index.html')
#app.route('/Analyze', methods=['GET'])
def analyze():
return render_template('analyze.html')
#(ignore this bulk one)
#app.route('/BulkAnalyze', methods=['GET'])
def bulk_analyze():
return render_template('Bulk.html')
#app.route('/api/Analyze', methods=['POST'])
def Submit():
pdf_file = request.files['FL']
jd_text = request.form['JD']
jd_text = " ".join(jd_text.split('\n'))
with fitz.open(pdf_file) as doc:
text = ''
for page in doc:
text += page.get_text()
text = ' '.join(text.split('\n'))
# Perform text comparison
matching_words = [word for word in jd_text.split() if word in text.split()]
match = 100 * len(matching_words) / len(jd_text.split())
return jsonify({'result': 'The matching percentage is :' + match })
if __name__ == "__main__":
app.run()
I was trying to compare those two text input to get a percentage output as an alert.
I am aware i could display output on page or another webpage to circumnavigate this issue, but this is not some irl problem and i would love to learn from this.
An uploaded file results in an object of type FileStorage on the server side. It is a file-like object for the loaded PDF file. It is not possible to extract the text directly from the FileStorage object. The data must first be read into a stream.
The following is the slightly modified example based on your code.
from flask import (
Flask,
jsonify,
redirect,
render_template,
request
)
import fitz
import io
import re
app = Flask(__name__)
#app.route('/')
def index():
return render_template('index.html')
#app.post('/api/analyze')
def api_analyze():
pcnt = 0
try:
desc = request.form['desc']
file = request.files['file']
with io.BytesIO(file.read()) as fh, fitz.open(stream=fh, filetype='pdf') as doc:
text = ' '.join(page.get_text() for page in doc)
tokens_desc = set(re.findall(r'\b\w+\b', desc))
tokens_text = set(re.findall(r'\b\w+\b', text))
tokens_match = tokens_text & tokens_desc
pcnt = len(tokens_match) / len(tokens_desc) * 100
finally:
return jsonify(result=f'The matching percentage is: {pcnt}%')
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Index</title>
</head>
<body>
<form name="upload-form">
<div>
<label for="file">Choose a file:</label>
<input type="file" name="file" id="file" accept="application/pdf" />
</div>
<div>
<label for="desc">Description:</label>
<textarea name="desc" id="desc" rows="4" cols="50"></textarea>
</div>
<div>
<input type="submit" value="Submit" />
</div>
</form>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
$(function() {
$('form[name="upload-form"]').submit(function(event) {
event.preventDefault();
const file = this['file'].files[0];
if (!file || file.type !== 'application/pdf') {
alert('Please select a valid PDF file');
return;
}
if (file.size > 5000000) {
alert('File size should not exceed 5 MB');
return;
}
$.ajax({
url: '/api/analyze',
type: 'post',
data: new FormData(this),
processData: false,
contentType: false
}).done(function(data) {
alert(data.result);
}).fail(function() {
alert('Error during API call.');
});
})
});
</script>
</body>
</html>

sending data, but result shows a GET request instead of POST

I am trying to use urllib to fill out a form and then retrieve the results from the submitted data.The app I'm posting to is on a server that I have to login through appgate to access. The POST form (that I see in the response in the terminal) is like this:
<form action="accuracy-upload3" method="post"
enctype="multipart/form-data">
Human: <input type="file" id="human" name="human"><br>
Machine: <input type="file" id="machine" name="machine"><br>
<input type="submit" class="submit" value="Submit" />
</form>
But even if the method is "POST" I seem to be doing a GET instead since the html from the url is all that returns, not the response from the url on the 'action' parameter. My code is as follows:
url = "https://accuracy3.html"
filename1 = 'human.txt'
filename2 = 'machine.txt'
filedata1 = open(filename1).read()
filedata2 = open(filename2).read()
values = {
"Human": filedata1,
"id": "human",
"name": "human",
"Machine": filedata2,
"id": "machine",
"name": "machine",
"value": "Submit"
}
req = urllib2.Request(url, data = urllib.urlencode(values), headers
=
{"Content-type": "application/x-www-form-urlencoded"})
response = urllib2.urlopen(req)
print response.read()
From Making a POST call instead of GET using urllib2 I see that it should be sending a POST since I've sent data, but it isn't doing that.
Can anyone see what the problem is with my script?

Passing File Objects with Django

I am attempting to retrieve a file and then upload it to Parse.com by submitting via POST. My HTML:
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<div class="container">
<form action="" id="fileupload" name="fileupload" enctype="multipart/form-data" method="post">
{% csrf_token %}
<fieldset>
<input type="file" name="fileselect" id="fileselect" /></input>
<input type="hidden" name="myFile" id="myFile" />
<input id="uploadbutton" type="submit" value="Upload to Parse" />
</fieldset>
</form>
</div>
And using the following function to retrieve the file:
<script type="text/javascript">
$(function() {
var file;
// Set an event listener on the Choose File field.
$('#fileselect').bind("change", function(e) {
var files = e.target.files || e.dataTransfer.files;
// Our file var now holds the selected file
file = files[0];
document.getElementById('myFile').value = file;
});
});
</script>
However, this "myFile" field is not posting the file as an object nor does it jive with the Parse API documentation, which appears to be looking for a file path name, which I don't think I can pull from an unknown machine.
import json,httplib
connection = httplib.HTTPSConnection('api.parse.com', 443)
connection.connect()
connection.request('POST', '/1/files/pic.jpg', open('myPicture.jpg','rb').read(), {
"X-Parse-Application-Id": "xxxxxxxxxxxxxxxxxxxxx",
"X-Parse-REST-API-Key": "xxxxxxxxxxxxxxxxxxxxxxx",
"Content-Type": "image/jpeg"
})
result = json.loads(connection.getresponse().read())
print result
This seems like it would be a common use case but the only documentation I found was for ajax, which I would prefer not to use because it exposes my API credentials https://www.parse.com/questions/uploading-files-to-parse-using-javascript-and-the-rest-api.
I am not sure what is the best way to handle the file... if there's a way to handle within the Django framework or if I need to convert to JSON. And, even when the file object is captured, I'm not clear on how to use the Parse.com API with the file object.
After some research, it turns out that the answer is pretty straightforward. Using the "Basic File Upload" documentation from the Django website: https://docs.djangoproject.com/en/1.8/topics/http/file-uploads/ and replacing
open('myPicture.jpg', 'rb').read()
in the Parse documentation (referenced in the question above) with
request.FILES['file']
I was able to successfully upload the file to Parse. No javascript necessary.

Uploading file with AngularJS fails

Below are the snippets of my code regarding file upload.
Here is my HTML code where I will choose and upload the file:
<form ng-click="addImportFile()" enctype="multipart/form-data">
<label for="importfile">Import Time Events File:</label><br><br>
<label for="select_import_file">SELECT FILE:</label><br>
<input id="import_file" type="file" class="file btn btn-default" ng-disabled="CutOffListTemp.id== Null" data-show-preview="false">
<input class="btn btn-primary" type="submit" name="submit" value="Upload" ng-disabled="CutOffListTemp.id== Null"/><br/><br/>
</form>
This is my controller that will link both html and my python file:
angular.module('hrisWebappApp').controller('ImportPayrollCtrl', function ($scope, $state, $stateParams, $http, ngTableParams, $modal, $filter) {
$scope.addImportFile = function() {
$http.post('http://127.0.0.1:5000/api/v1.0/upload_file/' + $scope.CutOffListTemp.id, {})
.success(function(data, status, headers, config) {
console.log(data);
if (data.success) {
console.log('import success!');
} else {
console.log('importing of file failed' );
}
})
.error(function(data, status, headers, config) {});
};
This is my python file:
#api.route('/upload_file/<int:id>', methods=['GET','POST'])
#cross_origin(headers=['Content-Type'])
def upload_file(id):
print "hello"
try:
os.stat('UPLOAD_FOLDER')
except:
os.mkdir('UPLOAD_FOLDER')
file = request.files['file']
print 'filename: ' + file.filename
if file and allowed_file(file.filename):
print 'allowing file'
filename = secure_filename(file.filename)
path=(os.path.join(current_app.config['UPLOAD_FOLDER'], filename))
file.save(path) #The end of the line which save the file you uploaded.
return redirect(url_for('uploaded_file',
filename=filename))
return '''
<!doctype html>
<title>Upload new File</title>
<h1>Upload new File</h1>
<p>opsss it seems you uploaded an invalid filename please use .csv only</p>
<form action="" method=post enctype=multipart/form-data>
<p><input type=file name=file>
<input type=submit value=Upload>
</form>
'''
And the result in the console gave me this even if I select the correct format of file:
<!doctype html>
<title>Upload new File</title>
<h1>Upload new File</h1>
<p>opsss it seems you uploaded an invalid filename please use .csv only</p>
<form action="" method=post enctype=multipart/form-data>
<p><input type=file name=file>
<input type=submit value=Upload>
</form>
This is not returning to my HTML and I cannot upload the file.
Hi I can finally upload the file, I change the angular part, I change it by this:
$scope.addImportFile = function() {
var f = document.getElementById('file').files[0]; console.log(f);
var formData = new FormData();
formData.append('file', f);
$http({method: 'POST', url: 'http://127.0.0.1:5000/api/v1.0/upload_file/' +$scope.CutOffListTemp.id,
data: formData,
headers: {'Content-Type': undefined},
transformRequest: angular.identity})
.success(function(data, status, headers, config) {console.log(data);
if (data.success) {
console.log('import success!');
}
})
.error(function(data, status, headers, config) {
});
// }
};
The first thing is about the post request. Without ng-click="addImportFile()", the browser will usually take care of serializing form data and sending it to the server. So if you try:
<form method="put" enctype="multipart/form-data" action="http://127.0.0.1:5000/api/v1.0/upload_file">
<label for="importfile">Import Time Events File:</label><br><br>
<label for="select_import_file">SELECT FILE:</label><br>
<input id="import_file" type="file" name="file" class="file btn btn-default" ng-disabled="CutOffListTemp.id== Null" data-show-preview="false">
<input class="btn btn-primary" type="submit" name="submit" value="Upload" ng-disabled="CutOffListTemp.id== Null"/><br/><br/>
</form>
and then in python, make your request url independent of scope.CutOffListTemp.id:
#api.route('/upload_file', methods=['GET','POST'])
It probably will work.
Alternatively, if you want to use your custom function to send post request, the browser will not take care of the serialization stuff any more, you will need to do it yourself.
In angular, the API for $http.post is:
$http.post('/someUrl', data).success(successCallback);
If we use "{}" for the data parameter, which means empty, the server will not find the data named "file" (file = request.files['file']). Thus you will see Bad Request
To fix it, we need to use formData to make file upload which requires your browser supports HTML5:
$scope.addImportFile = function() {
var f = document.getElementById('file').files[0]
var fd = new FormData();
fd.append("file", f);
$http.post('http://127.0.0.1:5000/api/v1.0/upload_file/'+$scope.CutOffListTemp.id,
fd,
headers: {'Content-Type': undefined})
.success......
Other than using the native javascript code above, there are plenty great angular file upload libraries which can make file upload much easier for angular, you may probably want to have a look at one of them (reference: File Upload using AngularJS):
https://github.com/nervgh/angular-file-upload
https://github.com/leon/angular-upload
......

how to store html form data into file

My HTML code:
<html>
<head>
<title>INFORMATION</title>
</head>
<body>
<form action = "/cgi-bin/test.py" method = "post">
FirstName:
<input type = "text" name = "firstname" /><br>
LastName:
<input type = "text" name = "lastname" /><br>
<input type = "submit" name = "submit "value = "SUBMIT">
<input type = "reset" name = "reset" value = "RESET">
</form>
</body>
My PYTHON CODE (test.py) which is in cgi-bin directory:
#!usr/bin/python
form = web.input()
print form.firstname
print form.lastname
what should i do to store html data in some file ??
Just write it to a file!
#!usr/bin/python
import cgi
form = cgi.FieldStorage()
with open ('fileToWrite.txt','w') as fileOutput:
fileOutput.write(form.getValue('firstname'))
fileOutput.write(form.getValue'(lastname'))
Oh, and you need to have write permission into the file. So for example if you are running apache, sudo chown www-data:www-data fileToWrite.txt should do it.
with open('/path/to/form.txt','w') as out_fh:
out_fh.write(form.firstname)
out_fh.write(form.lastname
The webserver will need to have write permission to the directory you want to create the file in.

Categories

Resources