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)>]}>
Related
I have django view that gets request and I try to send pdf result of copyleak scan.
I get file as request.body and request.FILES is empty.
I have checked copyleaks docs to see if I could pass extra argument as we should pass
enctype="multipart/form-data" in django form to get files in request.FILES, but I did not see anything related.
I can read request body and write it to file, no problem here, but would be great if I directly get pdf file in request FILES.
myobj = json.dumps(
{
"pdfReport": {
"verb": "POST",
"endpoint": "https://aa67-212-47-137-71.in.ngrok.io/en/tool/copyleaks/download/",
},
"completionWebhook": "https://aa67-212-47-137-71.in.ngrok.io/en/tool/copyleaks/complete/",
"maxRetries": 3,
}
)
response = requests.post(
"https://api.copyleaks.com/v3/downloads/file4/export/export16",
headers=headers,
data=myobj,
)
I tried to change Content-Type manually and got error
django.http.multipartparser.MultiPartParserError: Invalid boundary in multipart: None
Bad request (Unable to parse request body): /en/tool/copyleaks/download/
I have a form in the front-end having multiple entries, i.e name, email, phone and also a file field entry. A Form group is used to group all these elements in the same form in Angular. There is also a corresponding model in Django, (Using Django Rest Framework).
I could not manage to have the file sent to the API, even if the rest of the data is sent correctly and saved on the back-end.
First, I am able to upload the file successfully to Front-end, below I log in the console:
Second, the object I send is something like this:
{"name":"name", "age":49, "email":"email#field.com", "file":File}
The File in the JSON is the same file object displayed in the console above.
I tested my backend with Postman, I was able to succesfully have the file as well as the other data saved. (I believe the problem to be more on the Front-end side ).
Solutions I found for uploading file in Angular used form data (i.e here), these solutions were not convenient as the form consists only of a file, however in my case I have file as well as other data (Form Group).
Another thing I tried that did not work was the following: putting a form Data object with the file in the "file" key of the JSON to be sent. Still, this it did not work.
Also, this is how I upload the file in angular:
public file: File | null = null;
public form: FormGroup;
formData = new FormData();
ngOnInit(){
this.form = this.fb.group({
name: [], [Validators.required]],
age: [],
email: [], [Validators.required]],
file: []});
fileUploadedHandler(file) {
this.file = file;
this.formData.append("file",file, file.name);
this.form.patchValue({file:file}); //this.formData});
this.createDocumentForm.updateValueAndValidity();
console.log(file);}
}
Any propositions to solve this ?
Managed to solve the problem. First I had to use formData instead of formGroup, It was also possible to have multiple fields in formData using append method :
this.formData.append("file",file, file.name);
this.formData.append("name",name);
this.formData.append("age",age);
I had also to revisit the HTTP headers used to submit the form to the API, this was the blocking part.
In my case I had to Remove the 'Content-Type': 'application/json' from the headers. The new working one was:
working_headers = new HttpHeaders({
"Accept": "*/*",
"Authorization": 'Token laksjd8654a6s56a498as5d4a6s8d7a6s5d4a',
});
Hi Have problem with downloading excel file from serve by url. The file is corrupted etc..
below is my download function vue
downloadFile() {
axios({
url: this.scenario.file,
method: 'GET',
headers: {'Accept': 'application/vnd.ms-excel'},
responseType: "arraybuffer"
}).then(response => {
const url = window.URL.createObjectURL(
new Blob([response.data], {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'})
);
const link = document.createElement("a");
link.href = url;
link.setAttribute('download', `file.xlsx`);
this.myresponseObject = response; // this line is just to save - url= window.URL.createObjectURL
this.blobUrl=url; // this line is just to save response object fro checking
document.body.appendChild(link);
link.click();
window.URL.revokeObjectURL(url);
link.remove();
});
},
in this code the url of the file which stored in the object scenario is -
this.scenario.file = "http://127.0.0.1:8000/media/datafiles/Input_curves_bm7ionE.xlsx"
I have saved the "response" to look at it after download attempt:
myresponseObject:Object
config:Object
adapter:ƒ xhrAdapter(config)
data:undefined
headers:Object
maxContentLength:-1
method:"get"
responseType:"arraybuffer"
timeout:0
transformRequest:Array[1]
transformResponse:Array[1]
url:"http://127.0.0.1:8000/media/datafiles/Input_curves_bm7ionE.xlsx"
validateStatus:ƒ validateStatus(status)
xsrfCookieName:"XSRF-TOKEN"
xsrfHeaderName:"X-XSRF-TOKEN"
data:ArrayBuffer
headers:Object
content-length:"1345"
content-type:"text/html; charset=utf-8"
date:"Mon, 08 Jun 2020 10:24:40 GMT"
server:"WSGIServer/0.2 CPython/3.7.7"
vary:"Cookie"
x-content-type-options:"nosniff"
x-frame-options:"DENY"
request:XMLHttpRequest
status:200
statusText:"OK"
And url created by window.URL.createObjectUR is:
"blob:http://127.0.0.1:8000/8a40ab70-1ce4-42d2-9176-935c10ef1526"
Which is different from the original:
url:"http://127.0.0.1:8000/media/datafiles/Input_curves_bm7ionE.xlsx"
Guess it should be like this.
So, excel file downloaded is 2kb and is corrupted, formats or file extension is invalid
Spent day on it.....
Regards
I'm trying to download a .gz file from a django server (Python 3.7) using Ajax post request. This is the minimal django view function and Ajax function to request download on client, compress a folder and send it (server) and receive the data on the client:
from pathlib import Path
def downloadfile(request):
folder = Path().home().joinpath('workspace')
tar_path = Path().home().joinpath('workspace.gz')
tar = tarfile.open(tar_path.as_posix(), 'w:gz')
tar.add(folder.as_posix(), arcname='workspace')
tar.close()
try:
with open(tar_path.as_posix(), 'rb') as f:
file_data = f.read()
response = HttpResponse(file_data, content_type='application/gzip')
response['Content-Disposition'] = 'attachment; filename="workspace.gz"'
except IOError:
response = HttpResponse('File not exist')
return response
This is the Ajax function on the client side:
$(function () {
$('#downloadfile').submit(function () {
$.ajax({
type: 'POST',
url: 'downloadfile',
success: function(response){
download(response,'workspace.gz', 'application/gzip');
}
});
return false;
});
});
function download(content, filename, contentType)
{
var a = document.createElement('a');
var blob = new Blob([content], {'type':contentType});
a.href = window.URL.createObjectURL(blob);
a.download = filename;
a.click();
}
A sample gzipped folder that is 36.5 KB will be inflated to 66.1 KB when downloaded and it clearly can't be extracted.
What I know:
The file is healthy and extractable on server side.
The data is transferred and downloaded on the client but inflated and broken.
The respone variable in the JavaScript function looks like binary data (no header whatsoever)
What I don't know:
Why is the data size increased even though I'm reading and sending the compressed file as binary and both content types are set to 'application/gzip'?
If something is added to the file, what is it and when is it being added?
Thank you,
After spending a few hours on this, the following worked for me.
The trick was to use the hexify on the Django view part. The sending part in the Django view should be :
try:
with open(tar_path.as_posix(), 'rb') as f:
file_data = binascii.hexlify(f.read())
response = HttpResponse(str(file_data), content_type='application/gzip')
response['Content-Disposition'] = 'attachment; filename="%s"' % userid
os.remove(tar_path.as_posix())
except IOError:
response = HttpResponse('File not exist')
return response
and the JS part should create a bytearray:
var r = response.substring(2, response.length - 1);
var typedArray = new Uint8Array(r.match(/[\da-f]{2}/gi).map(function (h) {
return parseInt(h, 16)
}));
download(typedArray, 'workspace.tar.gz', 'application/gzip');
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?