Skip to content

Instantly share code, notes, and snippets.

@penpenps
Created September 24, 2015 02:40
Show Gist options
  • Save penpenps/5350155f074d85bb1f24 to your computer and use it in GitHub Desktop.
Save penpenps/5350155f074d85bb1f24 to your computer and use it in GitHub Desktop.
Use XMLHttpRequest to upload file and handle it by Django
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" >
<title>XMLHttpRequest send file demo</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!--set Document Mode to IE=edge -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- Le styles -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div id="driver-uploader-detail" style='width:500px; margin:0 auto;'>
<div class='page-header'><h2>XMLHttpRequest send file demo</h2></div>
<input id="driver-uploader-path" type="file" class="filestyle" data-icon="true" data-buttonText="Browse" name="driver_file">
&nbsp;
<span id="driver-uploader-success-alert" class='text-success' style="display:none">Success!</span>
<span id="driver-uploader-failure-alert" class='text-danger' style="display:none">Failed!</span>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.5/js/bootstrap.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$('#driver-uploader-path').change(function(){
var file = this.files[0];
filename = '';
if('name' in file)
filename= file.name;
else
filename = file.fileName;
var xhr = new XMLHttpRequest();
(xhr.upload || xhr).addEventListener('progress', function(e) {
var done = e.position || e.loaded
var total = e.totalSize || e.total;
console.log('xhr progress: ' + Math.round(done/total*100) + '%');
});
xhr.addEventListener('load', function(e) {
data = JSON.parse(this.responseText);
if(this.status != 200){
$('#driver-uploader-failure-alert').show();
return;
}
$('#driver_source').val('Flat file on idisas');
$('#driver_name').val(data['file_remote_path']).blur();
$('#driver-uploader-success-alert').show();
});
xhr.open('post', '/your-sever-url', true);
var fd = new FormData();
fd.append("filename", filename);
fd.append("drive_file", file);
xhr.send(fd);
});
});
</script>
</body>
</html>
def upload_driver(request):
upload_file = request.FILES['drive_file']
ret = {}
if upload_file:
target_folder = settings.PULL_DRIVER_UPLOAD_PATH
if not os.path.exists(target_folder): os.mkdir(target_folder)
rtime = str(int(time.time()))
filename = request.POST['filename']
target = os.path.join(target_folder, filename)
with open(target, 'wb+') as dest:
for c in upload_file.chunks():
dest.write(c)
ret['file_remote_path'] = target
else:
return HttpResponse(status=500)
return HttpResponse(json.dumps(ret), mimetype = "application/json")
@fe-iron
Copy link

fe-iron commented Sep 4, 2020

I'm handling the upload like this: the first user chooses or drops the file to upload then javascript will convert it into form data then javascript will send it to the views and in javascript, I did this to overcome that csrf error
// using jQuery
const csrftoken = jQuery("[name=csrfmiddlewaretoken]").val();
xmlhttp.open('post', o.options.processor);
xmlhttp.setRequestHeader("X-CSRFToken", csrftoken);
xmlhttp.send(data);

@runekaagaard
Copy link

It's a good example, but be aware that the python code is vulnerable to path manipulation. If you post "filename" with "../"'s it's possible to override any which file the process running the django service has access to. e.g.: "../../../../../root/.ssh/id_ed25519"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment