I need to let the Django auto download the generated file.
Tried all different solutions online, none of them works.
Views.py
def validate(request):
if request.method == 'POST':
filename = request.POST.get('source_file')
file_path = os.path.join(settings.MEDIA_ROOT, 'SourceFiles', filename)
region = request.POST.get('region')
product_type = request.POST.get('product_type')
result = validateSource.delay(file_path, region, product_type)
output_filepath, log_filepath = result.get()
if os.path.exists(output_filepath) and os.path.exists(log_filepath):
zip_filename = zipFiles([output_filepath, log_filepath], filename)
zip_filepath = os.path.join(settings.MEDIA_ROOT, zip_filename)
response = FileResponse(open(zip_filepath, 'rb'), as_attachment=True)
return response
raise Http404
Template: code for the form POST.
$(document).on('submit', '#productForm', function(e){
e.preventDefault();
var inputFilePath = document.getElementById('sourceFileInput').files.item(0).name;
$.ajax({
method: 'POST',
url: 'validate/',
data: {
source_file: inputFilePath,
region: $("#Region-choice").val(),
product_type: $("#Product-type").val()}
})
.done(function(){
document.getElementById('lblStatus').innerHTML = "Result: <br/>"
document.getElementById('lblStatusContent').innerHTML = "Success!"
})
.fail(function(req, textStatus, errorThrown) {
document.getElementById('lblStatus').innerHTML = "Result: <br/>"
alert("Something went wrong!:" + textStatus + ' ' + errorThrown )
});
});
});
It's not possible to download files to your computer via an ajax (XHR) request. So you need to redirect the user actually (setting window.location) to a view that downloads the file. Or you can add as a result of the successful POST a button the current page so the user can download the file. In any case, you need to move the file download to a different view so a standard GET request can fetch it.
But your code to return the file in Django (using FileResponse) is correct.
There's also an explanation with an alternative way of doing it here
def validate(request):
if request.method == 'POST':
filename = request.POST.get('source_file')
file_path = os.path.join(settings.MEDIA_ROOT, 'SourceFiles', filename)
region = request.POST.get('region')
product_type = request.POST.get('product_type')
result = validateSource.delay(file_path, region, product_type)
output_filepath, log_filepath = result.get()
if os.path.exists(output_filepath) and os.path.exists(log_filepath):
zip_filename = zipFiles([output_filepath, log_filepath], filename)
zip_filepath = os.path.join(settings.MEDIA_ROOT, zip_filename)
with open(zip_filepath, 'rb') as fh:
response = HttpResponse(fh.read(), content_type="application/force-download")
response['Content-Disposition'] = 'attachment; filename=' + os.path.basename(zip_filepath)
return response
raise Http404
Related
This is my Kotlin code
imageButton.setOnClickListener {
val gallery = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.INTERNAL_CONTENT_URI)
startActivityForResult(gallery, pickImage)
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == RESULT_OK && requestCode == pickImage) {
imageUri = data?.data
imageView.setImageURI(imageUri)
//get email from preferences
val prefs = getSharedPreferences("db", Context.MODE_PRIVATE)
val email = prefs.getString("email", "")
val client = AsyncHttpClient(true, 80, 443)
val data = JSONObject()
data.put("files", imageUri.toString())
data.put("email", email.toString())
val condata = StringEntity(data.toString())
//post it to api
client.post(this, "https://jereson.pythonanywhere.com/editdp",
condata, "multipart/form-data; boundary=eBayClAsSiFiEdSpOsTiMaGe",
object: JsonHttpResponseHandler() {
override fun onSuccess(
statusCode: Int,
headers: Array<out Header>?,
response: JSONObject?
) {
Toast.makeText(applicationContext, "image updated successfully", Toast.LENGTH_LONG).show()
}
override fun onFailure(
statusCode: Int,
headers: Array<out Header>?,
responseString: String?,
throwable: Throwable?
) {
Toast.makeText(applicationContext, "Something went wrong "+statusCode, Toast.LENGTH_LONG).show()
}
})//ends the client.post
}//ends resultcode if
This is my python code
#app.route('/editdp', methods = ['POST', 'GET'])
def editdp():
connection = pymysql.connect(host ='jereson.mysql.pythonanywhere-services.com', user
='jereson', password ='jemuki.compassword#4321', database ='jereson$jemuki_com254_254')
cursor = connection.cursor()
from flask import request
json = request.json
email = json['email']
files = json['files']
files = request.files.getlist('files')
#print(files)
for file in files:
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
cursor.execute('UPDATE signup SET dp=%s WHERE email=%s ',[filename, email])
connection.commit()
print(file)
cursor.close()
response = jsonify({"message":"updated successfully"})
return response
When i post an image the code Toasts image updated successfully but whenever i check mysql the filename is not uploaded and also in the folder the image is not uploaded.The email from preferences is just to enable me update the image to the correct rowAny help would be highly appreciated.
I tried using
GET https://graph.microsoft.com/v1.0/me/photo/$value to get the user's image/photo but it only returns an HTTP 200 status code. How can I get the binary data?
I've also tried using the content.property as suggested in a similar post but get a .format is not an attribute of the dict.
#app.route("/photo")
def get_photo():
token = _get_token_from_cache(app_config.SCOPE)
if not token:
return redirect(url_for("login"))
photo = requests.get(app_config.PHOTO_ENDPOINT,
headers={'Authorization': 'Bearer ' + token['access_token']})
print(photo.status_code)
return photo
Gets a profile photo, and optionally saves a local copy. Returns a tuple of the raw photo data, HTTP status code, content type, and saved filename. Refer to this sample.
def profile_photo(session, *, user_id='me', save_as=None):
"""Get profile photo, and optionally save a local copy.
session = requests.Session() instance with Graph access token
user_id = Graph id value for the user, or 'me' (default) for current user
save_as = optional filename to save the photo locally. Should not include an
extension - the extension is determined by photo's content type.
Returns a tuple of the photo (raw data), HTTP status code, content type, saved filename.
"""
endpoint = 'me/photo/$value' if user_id == 'me' else f'users/{user_id}/$value'
photo_response = session.get(api_endpoint(endpoint),
stream=True)
photo_status_code = photo_response.status_code
if photo_response.ok:
photo = photo_response.raw.read()
# note we remove /$value from endpoint to get metadata endpoint
metadata_response = session.get(api_endpoint(endpoint[:-7]))
content_type = metadata_response.json().get('#odata.mediaContentType', '')
else:
photo = ''
content_type = ''
if photo and save_as:
extension = content_type.split('/')[1]
filename = save_as + '.' + extension
with open(filename, 'wb') as fhandle:
fhandle.write(photo)
else:
filename = ''
return (photo, photo_status_code, content_type, filename)
Alternate approach, based on the original question's code, if you want to display the resulting image on a web page.
from base64 import b64encode
#app.route("/photo")
def get_photo():
token = _get_token_from_cache(app_config.SCOPE)
if not token:
return redirect(url_for("login"))
response = requests.get(
app_config.PHOTO_ENDPOINT,
headers={'Authorization': 'Bearer ' + token['access_token']}
)
content_type = response.raw.getheader('Content-Type')
return render_template('index.html',
photo_data=b64encode(response.content),
photo_content_type=content_type)
Then in the index.html template you can display the photo like so:
<html>
<body>
<img src="data:{{ photo_content_type }};base64,{{ photo_data }}" />
</body>
</html>
Call Api: -
Axios.get('https://graph.microsoft.com/v1.0/me/photo/$value', {
headers: { 'Authorization': 'Bearer '+AccessToken },
responseType: 'blob'
}).then(o => {
const url = window.URL || window.webkitURL;
const blobUrl = url.createObjectURL(o.data);
self.setState({ imageUrl: blobUrl });
})
JSX: -
<img alt="image" src={this.state.imageUrl} />
Here is what worked for me:
from base64 import b64encode
token = _get_token_from_cache(app_config.graphSCOPE)
aadPhotoURI = "https://graph.microsoft.com/v1.0/me/photo/$value"
response = requests.get(aadPhotoURI, headers={'Authorization': 'Bearer ' +
token['access_token']},)
content_type = response.raw.getheader('Content-Type')
return render_template(
'usersettings.html',
photo_data = b64encode(response.content).decode(),
photo_content_type = content_type)
then in the .html page added:
<img class="account-img" alt="" src="data:{{ photo_content_type }};base64,{{ photo_data }}"/>
CSS for account-img:
.account-img {
width: 40px;
float: right;
border-radius: 50%;
}
i have a node server and a django server. I try to send large file from the node to the django server.
I send the large file from node server by using fs.createReadStream() function. Each chunk created is send to the django server.
I'am new in Django, so i don't know how to handle chunks. I tried to look the doc, but nothing seems clear for me.
I need to store entire file in MEDIA_ROOT path.
var output = fs.createWriteStream("../tmp_upload/" + pathname.split('/')[0] + ".zip");
archive.pipe(output);
archive
.directory('../tmp_upload/' + pathname.split('/')[0])
.finalize();
output.on('close', function(){
const stats = fs.statSync("../tmp_upload/" + pathname.split('/')[0] + ".zip")
const fileSizeInBytes = stats.size
let content = fs.createReadStream("../tmp_upload/" + pathname.split('/')[0] + ".zip")
var chunk_sum = 0
var index = 0
content.on('data', chunk => {
chunk_sum += chunk.length
const data = {
token: req.session.userToken,
patientfile: {
file: chunk.toString(),
sumOfChunks: chunk_sum,
fileSize: fileSizeInBytes,
index : index,
label: pathname.split('/')[0] + ".zip",
category: "OT",
}
};
index += 1
Store.patientFileAdd(data) // here is where i send the chunk to django
});
here is a part of my nodejs function
class PatientFileAdd(views.APIView):
permission_classes = (AllowAny, )
def post(self, request, *args, **kwargs):
try:
filedata = request.data['patientfile']
file = filedata['file']
file_start = filedata['index']
upload_folder = "/patient/patient_%s" % request.userprofile.patientaccount, filedata['label']
with open(upload_folder, 'wb+') as destination:
for chunk in file.chunks():
destination.write(chunk)
return toolsViews.ResponseHandler(
status.HTTP_202_ACCEPTED,
{
'patientfile': 'OK'
}
)
Here my Django view
Thanks
I'm attempting to submit my form, but it continually fails as there's something wrong with the POST. I'm unsure where/what exactly is causing the server to not process the request whether it's related to syntax, request routing, etc. I've also commented out every line related to file uploads, as well as comment out the if (validated) statement. There are no errors in the console as a result of this, but the form submission still fails. I'd appreciate any help/direction thanks.
I get this error message when I submit the form:
POST http://127.0.0.1:5051/register/ 400 (BAD REQUEST)
views.py
#blueprint.route("register/", methods=['GET', 'POST'])
def register():
"""Renders register page."""
form = RegisterForm()
if request.method == 'POST':
if not form.validate_on_submit():
return render_template('main/register.html', page_title="Service Registration",
form=form, form_success=False, media_types=current_app.config["ACCEPTED_"
"MEDIA_TYPE"])
ticket, err = create_ticket2(customer_id, organization + "\n" + venue_name + "\n" + street + "\n" + country + "\n" + teamviewquestion + "\n" + teamviewerid + "\n" + deviations + "\n" + deviationsnotes + "\n" + displaydirector + "\n" + composer + "\n" + decryptor + "\n" + motionrocket + "\n" + othersoftware,
location=location)
if err:
return render_template('main/register.html', page_title="Service Registration",
form=form, form_success=False, message=err, media_types=current_app.config["ACCEPTED_"
"MEDIA_TYPE"])
else:
success_msg = "Error"
.format(ticket.get('id'))
return render_template('main/register.html', page_title="Service Registration",
form=form, form_success=True, message=success_msg, media_types=current_app.config["ACCEPTED_"
"MEDIA_TYPE"])
return render_template('main/register.html', page_title="Service Registration",
form=form, media_types=current_app.config["ACCEPTED_"
"MEDIA_TYPE"])
"""Handles file upload POSTs."""
first_name = request.form.get("first_name")
last_name = request.form.get("last_name")
name = request.form.get("first_name") + " " + request.form.get("last_name")
email = request.form.get("email")
filename = request.form.get("filename")
file_type = request.form.get("file_type")
if filename == '':
response = make_response("No selected file")
return response, 400
if check_file_type(file_type):
filename = clean_filename(filename)
filename = secure_filename(filename)
filename = unique_filename(filename)
response = generate_presigned_post(filename, file_type)
# CREATE DB REFERENCE
url = "http://nevcodocs.s3.amazonaws.com/Uploads/{}".format(filename)
instance = CustomerFileUpload.query.filter_by(url=url).first()
if not instance:
instance = CustomerFileUpload(url=url, email=email, name=name)
db.session.add(instance)
db.session.commit()
else:
instance.update(created_at=datetime.utcnow())
return response, 200
js (ticket submission function)
$('#ticket-form').submit(function(event) {
if (validated) {
$('#filename').val($('#upload').val());
$.ajax({
type: 'POST',
url: '/register/',
data: $('#ticket-form').serialize()
}).done(function(data) {
var formData = new FormData();
for (var key in data.data) {
formData.append(key, data.data[key]);
}
formData.append('file', $('#upload').prop('files')[0]);
formData.append('csrf_token', '{{ csrf_token }}');
var req = new XMLHttpRequest();
req.onload = function() {
showSpinner(false);
$('#ticket-form').removeClass("support-form-show");
$('#ticket-form').addClass("support-form-hide");
};
req.onerror = function() {
showSpinner(false);
$('#ticket-form-failed').removeClass("support-form-hide");
$('#ticket-form-failed').addClass("support-form-show");
};
req.open('POST', '/register/');
req.send(formData);
}).fail(function(err) {
showSpinner(false);
$('#ticket-form-failed').removeClass("support-form-hide");
$('#ticket-form-failed').addClass("support-form-show");
});
} else {
showSpinner(false);
enableSubmit(true);
}
});
Usually, bad request means that you're trying to fetch data from request object using invalid keys. So you need to make sure that your POST request body (that was sent by javascript) contains all keys which you're using as arguments of request.form.get() method: first_name, last_name, etc...
I'm using cytoscape.js to create a menu where I can download files quickly. I'm using an Ajax POST in order to pass the file name back to flask in order to download. For some reason, I can get all the information back but for whatever reason I cannot get the file to download. I've tried two methods so far.
AJAX Post:
{{
content: 'Download',
select: function(ele) {{
//this is to get the name of URI
var loc = window.location.pathname
var postData = {{
"element": ele.id(),
"source": loc
}}
$.ajax({{
url: '/get_file',
type: "POST",
contentType: 'application/json',
data: JSON.stringify(postData),
dataType: 'json',
success: function(response) {{
console.log("got it!")
}},
error: function(xhr) {{
console.log("Nope!")
}}
}})
Now for the flask back end, we have method one, and the commented section shows method 2 & 3 (in the if loop (if os.path.isfile(SAVE_PATH)):
#app.route('/get_file', methods=['POST'])
def get_file():
print("This is request data: {}".format(request.data))
requests = request.get_json()
element = requests['element']
source = requests['source']
#this is where loc is retrieved from ajax post, in format of /static/{filename}.html
for change in ['/static/', '.html']:
if change in source:
source = source.replace(change,"")
print("source: {}".format(source))
SAVE_PATH = os.path.curdir + "/results/" + source + "/" + element
SAVE_DIRECTORY = os.path.curdir + "/results/" + source + "/"
if os.path.isfile(SAVE_PATH):
downloaded_file = open("{}".format(SAVE_PATH), 'rb').read()
#res = send_from_directory(SAVE_PATH.replace("./", ""), element, attachment_filename=element, mimetype="application/octet-stream", as_attachment=True)
#res = send_file(SAVE_PATH, as_attachment=True, attachment_filename=element, mimetype='application/octet-stream')
#return res
return Response(
downloaded_file,
mimetype="application/octet-stream",
headers={"Content-disposition":
"attachment; filename={}".format(element)})
else:
print("failed")
return "failed"
Now I'm getting all the correct response, when I print out downloaded_file, I get the binary output, but for whatever reason, it just isn't downloading.
Looks like you could construct the download path on the frontend and request the file directly, something like this:
location = loc.split("/");
path = "results/" + location[location.length - 1].split(".")[0] + "/" + ele.id();
window.location.href = path;