I'm using Valumns File Uploader to load files to django. This supports an ajax upload via XHR for modern browsers and an iFrame fallback for older ones like IE.
Now the problem: If I upload large files, only iFrame upload works, because here the files are mapped into request.FILES and django writes them to the disk immediately instead of memory.
If XHR upload is used, I have to read request._raw_post_data and write this to disk, but it fails with an MemoryError.
This is my file uploader initialization:
var uploader = new qq.FileUploader({
'action': uploadUrl,
'multiple': true,
'allowedExtensions': allowedExtensions,
'element': selector,
'debug': true,
'onComplete': completeFunction,
'onProgress': progressFunction,
'onSubmit': submitFunction
});
At the django end I use the following code to write the file content to disk:
# open a new file to write the contents into
new_file_name = str(uuid.uuid4())
destination = open(upload_path + new_file_name, 'wb+')
# differentiate between xhr (Chrome, FF) and pseudo form uploads (IE)
if len(request.FILES) > 0: # IE
for chunk in request.FILES[0].chunks():
destination.write(chunk)
else: # others
destination.write(request._raw_post_data)
destination.close()
I also tried this solution from Alex Kuhl, but this fails with an IOError: request data read error.
Is there any way to get the files uploaded via XHR into request.FILES and so use the django builtin handling?
Related
I'm trying to upload a CSV file using Angular HTTP Client. But when i check the request.FILES in backend it shows <MultiValueDict: {}>. Apparently the file data is coming in request.body as byte string. Below is sample angular code for you reference.
const upload_url = `${BASE_URL}/data-upload`;
// Create form data instance
const formData: FormData = new FormData();
formData.append('data_file', file, file.name);
// Update header
const headers = {'Content-Type': 'multipart/form-data'}
this.http.post(upload_url, formData, {headers: headers}).subscribe(res => {
console.log(res);
});
How can i get the same file data in request.FILES?
Problem Solved! File upload infers Content-Type Header while uploading the data to the server.
I have removed the header from the above code and uploaded the file and it worked perfectly.
Here's the response after uploading the file from request.FILES: <MultiValueDict: {'data_file': [<TemporaryUploadedFile: dummy-data.csv (application/vnd.ms-excel)>]}>
I am using
storages.backends.s3boto3.S3Boto3Storage
storage backend to upload files in my django project.
field declaration in model:
document = models.FileField(upload_to=s3_directory_path.user_directory_path)
user_directory_path
def user_directory_path(instance, filename):
# TODO: Try to include this along with check filetype on the request object
document = instance.document
mime = magic.from_buffer(document.read(), mime=True)
extension = mimetypes.guess_extension(mime, strict=False)
file_name = str(uuid.uuid4()) + extension
document.seek(0)
return os.path.join("users", str(instance.user.id), file_name)
The saving of the document works perfectly fine, but the link which is generated force downloads the file. How can i avoid that?
Have a look at this answer to a general question about forcing file downloads via HTTP response headers. See also the MDN docs about Content-Disposition.
Can you show us the response headers you get when visiting the document URL?
It would be interesting to see how S3 delivers your files.
If you cannot change the headers in S3, you have the option to write a Django view that proxies the file download. Alternatively, configure your webserver (i.e. NGINX) to act as a proxy and set the required headers).
For Django, this section of the docs will show you how to set the headers.
response = HttpResponse(
document,
headers={
'Content-Type': mimetype,
'Content-Disposition': f'attachment; filename="{document.name}"',
}
)
I want to develop a simple web server using python to handle some simple http request. I have learn how to response the request, such as transferring html pages or transferring some other file. When I transfer a image file, a client use a browser to get the file, the url is like below:
http://114.212.82.104:8080/1.png
I set 'Content-Type = application/x-png'. But the browser directly download the file, and can not display in the browser. Not like the image below
https://www.baidu.com/img/bd_logo1.png
it can display in the browser. How to display the image in the browser?
Can someone help me?
and i know i can encode the image file into html page to fix it. code like below:
class RequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
def do_GET(self):
path = os.getcwd()+ self.path
if os.path.isfile(path):
with open(path,'rb') as fileTrans:
content = fileTrans.read().encode('base64').replace('\n','')
#self.sendContent(200, content)
self.send_response(200)
page = "<p>\"fef\"</p><img src=\"data:image/jpg;base64,{0}\"/>"
contentPage = page.format(content)
self.send_header('Content-Type', 'text/html')
self.send_header("Content-Length", str(len(contentPage)))
self.end_headers()
self.wfile.write(contentPage)
else:
self.sendContent(404,"file do not exists")
But I know there must be another way, i see the source code of URL(https://www.baidu.com/)
it just use
<img hidefocus="true" src="//www.baidu.com/img/bd_logo1.png" width="270" height="129"></div><a href="/" id="result_logo" onmousedown="return c({'fm':'tab','tab':'logo'})">
different from my page:
<p>"fef"</p><img src="data:image/jpg;base64,iVBORw0KGgoAAAANSUhEUgAAAcIAAAJYCAIAAAB+b3GqAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAvppVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTMyIDc5LjE1OTI4NCwgMjAxNi8wNC8xOS0xMzoxMzo0MCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6ODg3NkM1Njg1MzVFMTFFNkE0NkJFNTEzMUFCNzc4RTMiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6ODg3NkM1Njc1MzVFMTFFNkE0NkJFNTEzMUFCNzc4RTMiIHhtcDpDcmVhdG9yVG9vbD0iOC4xLjMiPiA8eG1wTU06RG......
OK,I think I have solved this problem.
Just set the attribute - 'Content-Type' of header as 'image/png' instead of 'application/x-png'.
I am using RecorderJS in my django application. In this, multiple audio files are created in the browser. My question is how can I store these files in the server (directly from the browser).
I have got few leads like using upload_to in FileField (which can be stored via forms) or using file-based sessions in Django. However, I am not sure how to proceed as it seems complicated for me to combine the following reasons:
multiple files to be stored simulataneously,
and storing directly from browser (not manually uploading in the browser).
Does anyone have solution to this. Thanks in advance.
[Update]
I have proceeded the direction as shown below in the form of a code:
In urls.py
url(r'^audio_file/$', 'nalign_app_recorder.views.recorder'),
In models.py
class InputFile(models.Model):
audio_file = models.FileField(upload_to='/audio')
input_user = models.ForeignKey(User)
rec_date = models.DateTimeField('date recorded', auto_now_add=True)
I am sending the audio file (blob) via Ajax Jquery.
function uploadBlob(blob) {
var fd = new FormData();
fd.append('fname', 'test.wav');
fd.append('data', blob);
$.ajax({
type: 'POST',
url: '/audio_file/',
data: fd,
processData: false,
contentType: false,
success: function(response) {
console.log("everything worked!");
$("#audio_file").html(response);
},
error: function(obj, status, err) { alert(err); console.log(err); }
});
Then I receive this file in the Django view [views.py]. However, though the file is received but the error is generated when the save() method is invoked. Does anyone know the solution for this or is there any better method:
#csrf_exempt
def recorder(request):
if request.method=='POST' or request.is_ajax():
e1=InputFile()
e1.audio_file=request.FILES #<-- Audio file is received here
e1.input_user=request.user
e1.rec_date=datetime.datetime.now()
e1.save() #<-- When save() method is executed, **error** is generated
return HttpResponseRedirect(--another-page--)
return render_to_response('recorder2.html',RequestContext(request))
Due to security reasons browsers don't allow you to set value of <file> form field. (Imagine hiding this field and setting the value to some vulnerable file).
You need to post the file via JavaScript.
I'm trying to upload a file into my web service (written using DJango REST framework). I have written the following code but I get data can not be converted to utf-8 error
with open('/images/img.jpg', 'rb') as imgFile:
content = imgFile.read ()
json = { 'fileName': 'img.jpg', 'img': content}
json_data = simplejson.dumps(json)
reqURL = urllib2.Request("http://localhost:8000/uploadfile/",json_data)
opener = urllib2.build_opener()
f = opener.open(reqURL)
What is the right way of passing file content over JSON?
You don't send files like this. File contents are sent by embedding them inside the request body.
You may be better of by using the beautiful python-request library. Check out the file upload section.