how to get NOT crashed image file from Unity to Django? - django

I'm using Unity 2018.3. and try to HTTP POST Request with image from Unity to Django.
try to take a picture in Unity and then POST the image to Django server.
I want to receive in server and make it to image file.
well, when i send for image file to byte[] using EncodeToPNG() or EncodeToJPG(), the server got it but when i print it the data it was crash seems like encoding error. so it can't write to image format. (the take a picture code is working right.)
Django server result image
i saw a bunch of things about this issue so i tried to other way like use WWWform or JSON but anything couldn't works..
how to get image form Unity to Django?
All help appreciated! Thanks, all.
take a picture
void TakeSnapshot()
{
Texture2D snap = new Texture2D(frontCam.width, frontCam.height);
snap.SetPixels(frontCam.GetPixels());
snap.Apply();
_SavePath = pathForDocumentsFile("photo");
System.IO.File.WriteAllBytes(_SavePath + ".png", snap.EncodeToPNG());
bytes = snap.EncodeToPNG();
//bytes = snap.EncodeToJPG();
UnityEngine.Object.Destroy(snap);
path = _SavePath + ".png";
StartCoroutine(ServerThrows());
}
POST to server
IEnumerator ServerThrows()
{
List<IMultipartFormSection> formData = new List<IMultipartFormSection>();
formData.Add(new MultipartFormDataSection("photo", bytes, "byte[]"));
//UnityWebRequest www = UnityWebRequest.Post(url, null, bytes);
UnityWebRequest www = UnityWebRequest.Post(url, formData);
www.chunkedTransfer = false;
yield return www.SendWebRequest();
if (www.isNetworkError || www.isHttpError)
{
Debug.Log(www.error);
}
else
{
Debug.Log("Form upload complete!" + www.downloadHandler.text);
}
}
response in server
def post(self, request, format=None):
print('get the data')
print('request.POST: ', request.POST)
print('request.headers: ', request.headers)
data_test = request.POST.get('photo', '')
print('data test is : ', data_test)
print('type of data_test is : ', type(data_test))
print('length of data_test is : ', len(data_test))
print('finish to get ')
# data_test = data_test.decode('utf-8').encode('euc_kr','replace')
f = open('./test.png','wb')
f.write(data_test.encode())
f.close()
#
data = open('./test.png', 'rb')
return HttpResponse("post !")

Related

Django acting weird on Windows server IIS deployment

I have the following view which allows me to save the information of a multi step application.
def saveNewApplication(request, *args, **kwargs):
educationList = [ val for val in pickle.loads(bytes.fromhex(request.session['education'])).values() ]
basicInfoDict = pickle.loads(bytes.fromhex(request.session['basic_info']))
documentsDict = pickle.loads(bytes.fromhex(request.session['documents']))
applicant, created = ApplicantInfo.objects.update_or_create(
applicantId=request.session['applicantId'],
defaults={**basicInfoDict}
)
if created:
#saving the diplomas
for education in educationList:
Education.objects.create(applicant=applicant, **education)
with open(f"{documentsDict['cv_url']}/{request.session['file_name']}", 'rb') as f:
Documents.objects.create(
applicant=applicant,
cv =File(f, name=os.path.basename(f.name)),
langue_de_travail = documentsDict['langue_de_travail']
)
#remove the temporary folder
shutil.rmtree(f"{documentsDict['cv_url']}")
else:
educationFilter = Education.objects.filter(applicant=applicant.id)
for idx, edu in enumerate(educationFilter):
Education.objects.filter(pk=edu.pk).update(**educationList[idx])
#updating the documents
document = get_object_or_404(Documents, applicant=applicant.id)
if documentsDict['cv_url']:
with open(f"{documentsDict['cv_url']}/{request.session['file_name']}", 'rb') as f:
document.cv = File(f, name=os.path.basename(f.name))
document.save()
document.langue_de_travail = documentsDict['langue_de_travail']
document.save()
languagesDict = pickle.loads(bytes.fromhex(request.session['languages']))
Languages.objects.update_or_create(applicant=applicant, defaults={**languagesDict})
if 'experiences' in request.session and request.session['experiences']:
experiencesList = [ pickle.loads(bytes.fromhex(val)) for val in request.session['experiences'].values() ]
Experience.objects.filter(applicant=applicant.id).delete()
for experience in experiencesList:
Experience.objects.create(applicant=applicant, **experience)
return JsonResponse({'success': True})
In the development it works perfectly but if deployed I am getting a 404 raise by this line get_object_or_404(Documents, applicant=applicant.id) meaning the creating is false. and I can't figure why is that.
The weirdest thing is if I do comment the entire else block it also returns a 500 error but this time it I do click in the link of the console it show the right response not redirected {success:true}
down below is my javascript fonction for handling the view.
applyBtn.addEventListener("click", () => {
var finalUrl = "/api/applications/save-application/";
fetch(finalUrl)
.then(res => res.json())
.then(data => {
if (data.success) {
window.location.href = '/management/dashboard/';
} else {
alert("something went wrong, Please try later");
}
})
});
I am using postgresql as a database I deleted twice but nothing.
the url file is here.
path("api/applications/save-application/", views.saveNewApplication, name="save-new-application"),
path("api/applications/delete-applicant/<slug:applicantId>/", views.deleteApplicant , name="delete-applicant"),
path('api/edit-personal-info/', editPersonalInfo, name="edit-personal-info"),
Any help or explanation would be highly appreciated. Thanks in advance.

Remove uploaded files with filepond

I really enjoy the filepond library and would like to implement it in my flask app. Since I was not able to find any useful examples online, I started to write my own, small, proof of concept web application. I would like to upload multiple images to the server and save the filenames in the database. Furthermore, I would like to edit an entry and add additional files or remove the existing ones.
So far I figured out how to upload and revert files before the form is submitted. I am also able to load existing files inside the edit form. Just when I click the 'x' button on a loaded image inside the edit form the image is removed from the filepond window and a 'removefile' event is fired, but the file still remains on the server. Is it possible to trigger the revert request on a loaded file or is there a better solution altogether?
x-button does not remove the file from the server
Here are the relevant snippets from my js file:
FilePond.registerPlugin(
FilePondPluginFileValidateSize,
FilePondPluginImagePreview,
FilePondPluginFileRename,
FilePondPluginFileValidateType
);
inputElement = document.querySelector(".filepond");
token = document
.querySelector('input[name="csrf_token"]')
.getAttribute("value");
FilePond.setOptions({
server: {
headers: { "X-CSRF-TOKEN": token },
process: "./process",
revert: "./revert",
load: {
url: "../",
}
},
});
const filepond = FilePond.create(inputElement, {
// Here I pass the files to my edit form in the following format:
//
// files: [
// {
// source: 'static/images/some_name.png',
// options: {
// type: 'local'
// }
// }]
});
The relevant code from .py file:
#app.route("/process", methods=["POST"])
#app.route("/edit/process", methods=["POST"])
def process():
upload_dir = "static/images"
file_names = []
for key in request.files:
file = request.files[key]
picture_fn = file.filename
file_names.append(picture_fn)
picture_path = os.path.join(upload_dir, picture_fn)
try:
file.save(picture_path)
except:
print("save fail: " + picture_path)
return json.dumps({"filename": [f for f in file_names]})
#app.route("/revert", methods=["DELETE"])
#app.route("/edit/revert", methods=["DELETE"])
def revert():
upload_dir = "static/images"
parsed = json.loads(request.data)
picture_fn = parsed["filename"][0]
picture_path = os.path.join(upload_dir, picture_fn)
try:
os.remove(picture_path)
except:
print("delete fail: " + picture_path)
return json.dumps({"filename": picture_fn})
Here is the repository to my full flask-filepond app:
https://github.com/AugeJevgenij/flask_filepond
Please excuse me if the question is unclear, does not make sense or the code is written poorly.
I just started programming a few months ago.
Acording to filepond documentation you can remove a file stored locally on the server like this:
FilePond.setOptions({
server: {
remove: (source, load, error) {
// 'source' is the path of the file and should be sent to a server endpoint via http
// call the load method before ending the function
load()
}
}
})
then on your server where you receive the source (path), use it to delete the file. Keep in mind that this is a risky approach to get your website hacked!

Django: Problem with ContentFile: String content is not downloaded completely

I'm quite new to using Django. As first project I wrote a little tool to create M3U8-Playlists.
My problem is, that long playlists are not transferred completely.
This is the stripped-down code:
def create(request):
# just a dummy filelist
playlist = ["#EXTM3U"] + 5 * ["/home/pi/music/" + 5 * "äöü0123456789á/" + "xyz.mp3"]
file_to_send = ContentFile("")
for item in playlist:
file_to_send.write("{}\n".format(item.replace("/home/pi/Music", r"\\raspberry\music").replace("/", "\\")))
response = HttpResponse(file_to_send, "audio/x-mpegurl")
response["Content-Length"] = file_to_send.size
response["Content-Disposition"] = f"attachment; filename=\"playlist.m3u8\""
# print some debug info
print("lines:", len(playlist), "chars (no linebreaks)", sum([len(entry) for entry in playlist]),
"filesize:", file_to_send.size)
return response
The problem seems to lie in the non-ascii chars in playlist entries (äöüá). When there are no such characters, the file is transferred intact. I assume that these are characters that use two bytes in UTF-8, but writing strings to the ContentFile like I do is probably not correct.
Found the answer, while working on the problem description.
This works:
def create(request):
# just a dummy filelist
playlist = ["#EXTM3U"] + 5 * ["/home/pi/music/" + 5 * "äöü0123456789á/" + "xyz.mp3"]
joined_playlist = "\n".join([item.replace("/home/pi/Music", r"\\raspberry\music").replace("/", "\\") for item in playlist])
file_to_send = ContentFile(joined_playlist.encode("UTF-8"))
response = HttpResponse(file_to_send, "audio/x-mpegurl")
response["Content-Length"] = file_to_send.size
response["Content-Disposition"] = f"attachment; filename=\"playlist.m3u8\""
# print some debug info
print("lines:", len(playlist), "chars (no linebreaks)", sum([len(entry) for entry in playlist]),
"filesize:", file_to_send.size)
return response
The important difference is, that I don't write Strings to the ContentFile any longer, but a byte array, which I got through encoding the String in UTF-8.
HTH

Django exception handling - catching ghost error from server-side

I have a Django view that is responsible for providing raw data for graph rendering on server-side. When I run the app locally (I have Windows 10 on my machine), everything works fine. But when I run the app from the remote server (it's Ubuntu), I get an 500-error. This type of errors (when identical code is ok locally, but fails remotely), currently constitutes a serious issue for me in that on every such occasion it leads to very time-consuming - and seemingly unprofessional - process to identify and fix them. And my question is, what is the magic exception handling code snippet which would help me through the detailed exception message to client-side console.
To be more specific, consider the following (I deliberately provide the code as is):
Django view:
def graph_vendors_black_white(request):
try:
legal_entity_own_qs = get_sale_points(request.user.id)
list = []
data = [x.blacknwhite_agreement_count(True) for x in legal_entity_own_qs]
list.append({'name':u'В белую', 'data':data});
data = [x.blacknwhite_agreement_count(False) for x in legal_entity_own_qs]
list.append({'name':u'В чёрную', 'data':data});
data = [x.blacknwhite_agreement_count(None) for x in legal_entity_own_qs]
list.append({'name':u'Не выбрана опция', 'data':data});
legal_entity_own_list = [unicode(x.short_identifier_rus) for x in legal_entity_own_qs]
json_response = JsonResponse({'time_series':json.dumps(list, ensure_ascii=False).encode('utf8'),'categories':json.dumps(legal_entity_own_list, ensure_ascii=False).encode('utf8')})
return json_response
except:
user_msg, tech_msg = default_error_msg()
return JsonResponse(user_msg + '\n ' + tech_msg, status = 500, safe = False)
def default_error_msg():
user_msg = u'Что-то пошло не так'
exc_type, exc_obj, exc_tb = sys.exc_info()
fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
try:
console_msg = exc_obj[1]
except:
console_msg = str(exc_obj.message)
tech_msg = ('File - ' + fname + ' on line ' + str(exc_tb.tb_lineno) + '. \n' + \
'Error message - ' + console_msg + '\n' + \
'Exception type - ' + str(type(exc_obj)))
return user_msg, tech_msg
JS:
$.get('/graph_vendors_black_white/', function (response)
{
// ... some code
}).fail(function(json_result) {
$('#black_white_container').html(json_result.responseJSON)
});
When I run this locally, it's perfectly ok. From remote server, it throws 500 error and most surprisingly json_result does not contain error message. Whereas if I put something like a = 1/0, I get the error message in the container instead of graph.
To sum up, the question is, what is the generic exception handling code snippet which would transmit the detailed error message to the fail-function response parameter NO MATTER WHAT THE ERROR IS on the server-side

Django: redirect after file download

I'm working on a view in my Django 1.5 that allow me to download a file. The download process it's triggered by a button in the HTML page like this:
<input type="button" value="Download!" />
The url point to a view that manage the download:
def filedownload(request, filename):
down_file = File.objects.get(name = filename)
file_path = MEDIA_ROOT+str(down_file.file)
file_name = down_file.filecomplete()
if not Transaction.objects.filter(user = request.user, file = down_file):
transaction = Transaction.objects.create(date = datetime.now(), user = request.user, file = down_file, vote = False)
transaction.save()
fp = open(file_path, 'rb')
response = HttpResponse(fp.read())
fp.close()
type, encoding = mimetypes.guess_type(file_name)
if type is None:
type = 'application/octet-stream'
response['Content-Type'] = type
response['Content-Length'] = str(os.stat(file_path).st_size)
if encoding is not None:
response['Content-Encoding'] = encoding
if u'WebKit' in request.META['HTTP_USER_AGENT']:
filename_header = 'filename=%s' % file_name.encode('utf-8')
elif u'MSIE' in request.META['HTTP_USER_AGENT']:
filename_header = ''
else:
filename_header = 'filename*=UTF-8\'\'%s' % urllib.quote(file_name.encode('utf-8'))
response['Content-Disposition'] = 'attachment; ' + filename_header
return response
What I wanted to do it's to redirect the user to a success page right after they hit the downlad button but I can't find a way to do it.
I'm not concerned about interrupted or otherwise unsuccessful downloads since it's a school project.
He are all steps that you have to follow to run your code :
get the jQuery File Download which allows downloads with OnSuccess and OnFailure callbacks.
Here is a simple use case demo using the plugin source with promises. The demo page includes many other, 'better UX' examples as well.
$.fileDownload('some/file.pdf')
.done(function () { //redirect });
Here is a simple use case demo using the plugin source with promises. The demo page includes many other, 'better UX' examples as well.
You could set the href for the input to the download confirmation page you want to display, passing along the file name, then within the template for the confirmation page, set the onload event to redirect to actually do the download.
<body onload=window.location='/file/download/{{ file.name }}/'>
You can do it using ajax request waiting until the download fully successful.
in your view :
$.fileDownload('some/file.pdf')
.done(function () { //redirect
window.location = '/link';
})
.fail(function () { alert('File download failed!'); });
How to use the previous code:
first add a name or id or class to your link
download link
next: here i use id to identify the link #a_d*
<script type="text/javascript">
$(document).on("click", "#a_d", function () {
$.fileDownload(.done(function () { //redirect
window.location = '/link';})
});
});
</script>
done !!