How to recieve formdata in django backend - javascript

I want to send the recorded wecam video to django backend, But can't figure out how to generate the video in backend.
function sendVideoToAPI () {
const url = '/upload/'
let blob = new Blob(chunks, {type: media.type });
let fd = new FormData();
let file = new File([blob], 'recording');
fd.append('data', file);
fetch(url1, {
method: 'POST',
body: fd
})
.then(res => console.log(res))
.catch(err => console.log(err))
}
In django views how to generate the video
.Is there any way to do it..?
EDIT
Views.py
def upload(request):
if request.method == 'POST':
request.FILES.get('data') as f:
print(f.size)
print(type(f))
return redirect("/")
while running server it gives The following error
Error
request.FILES.get('data') as f:
^
SyntaxError: invalid syntax

in django's view you can access to your files through request like this:
request.FILES.get('data') as f:
# your code
NOTE: this will make you a 'TemporaryUploadedFile' which means that after working with that, it destroys automatically

Related

Messy Chinese filenames in FormData

I used the following js code to load a file with a Chinese filename into FormData and then upload it and found the filename garbled on the server side.
export async function uploadFile(file, url) {
let formData = new FormData()
formData.append('file', file.file)
file.status = 'loading'
let response = await fetch(url, { method: 'POST', body: formData})
file.status = response.ok
return response
}
How can I solve the filename garbling problem because the filenames in formdata seem to be ASCII encoded?
This question is used to share my solution. The code is below. I encoded the file name with encodeURIComponent and created a new File Object from it.
export async function uploadFile(file, url) {
let formData = new FormData()
const file_ = new File([file.file], encodeURIComponent(file.filename), {type: file.file.type});
formData.append('file', file_)
file.status = 'loading'
let response = await fetch(url, { method: 'POST', body: formData})
file.status = response.ok
return response
}
Afterwards I decode the filename with decodeURIComponent on the server side.

How to download remote image then upload image as an image file for form submission?

There are similar questions like this, this, this, and this, but none help.
In Node, the goal is to use the axios module to download an image from Twitter then upload this image as an image file as part of a form submission.
This code downloads the Twitter image, but the uploaded binary image is corrupted when it reaches the server (also our server).
The image must be uploaded in binary.
A form is required because other fields are also submitted with the binary image. These other form fields were removed to simplify the code sample.
const axios = require('axios');
const FormData = require('form-data');
let response = await axios.get('https://pbs.twimg.com/media/EyGoZkzVoAEpgp9.png', {
responseType: 'arraybuffer'
});
let imageBuffer = Buffer.from(response.data, 'binary');
let formData = new FormData();
formData.append('image', imageBuffer);
try {
let response = await axios({
method: 'post',
url: serverUrl,
data: formData,
});
// Do stuff with response.data
} catch (error) {
console.log(error)
}
You should pass the headers to the axios call using formData.getHeaders() to send a Content-Type header of multipart/form-data. Without it, a Content-Type header of application/x-www-form-urlencoded is sent. You could pass a responseType of stream to the axios call that downloads the image and add the stream to the form data.
You can also use axios.post to simplify the method call.
const url = 'https://pbs.twimg.com/media/EyGoZkzVoAEpgp9.png'
const { data: stream } = await axios.get(url, {
responseType: 'stream',
})
const formData = new FormData()
formData.append('image', stream)
try {
const { data } = await axios.post('http://httpbin.org/post', formData, {
headers: formData.getHeaders(),
})
console.log(data)
} catch (error) {
// handle error
}
You can use the fetch API to fetch the image as a blob object and append it to form data. Then simply upload it to its destination using Axios, ajax, or the fetch API:
const mediaUrl = "https://pbs.twimg.com/media/EyGoZkzVoAEpgp9.png"
fetch(mediaUrl)
.then((response) => response.blob())
.then((blob) => {
// you can also check the mime type before uploading to your server
if (!['image/jpeg', 'image/gif', 'image/png'].includes(blob?.type)) {
throw new Error('Invalid image');
}
// append to form data
const formData = new FormData();
formData.append('image', blob);
// upload file to server
uploadFile(formData);
})
.catch((error) => {
console.log('Invalid image')
});

Unable to get video file for S3 upload. (using Expo Camera)

I have been stuck with trying to upload a video to S3 for a while and was hoping to get some pointers. Currently, what I've read and was told is that we need to send an actual file to S3 and not the url (which we might do if we were sending it to the backend before aws).
I am trying to do this by
const getBlob = async (fileURi) => {
console.log('THIS IS IT', fileURi);
const resp = await fetch(fileURi);
const videoBody = await resp.blob();
console.log(videoBody);
};
getBlob(video.uri);
The problem I am having is I am unable to actually get the video file. When I stop recording a video with await camera.stopRecording(); what I get in return is
Object {
"uri": "file:///path/20DD0E08-11CA-423D-B83D-BD5ED40DFB25.mov",
}
Is there a recommended approach in order to successfully get the actual file in order to send it to S3 through the client?
The way I am trying to currently send the video which doesn't work is:
const formData = new FormData();
formData.append('file', video.uri);
await fetch(url, {
method: 'POST',
body: formData,
headers: {
'Content-Type': 'multipart/form-data'
}
url: refers to the presignedUrl we get in return from aws.
P.S - Sending to the server through a fetch call does work but I noticed this approach also leave the User waiting for 10+ seconds since I need to send the video to the server then wait for it to finish uploading in AWS.
Thank you for all the help.
If I understand correctly you know how to upload file to your own server, but you want to send it directly to S3.
In that case I would suggest to use presigned URLs. https://docs.aws.amazon.com/AmazonS3/latest/dev/PresignedUrlUploadObject.html
You can generate presigned URL on your backend, it is basically regular URL pointing to S3 file and some key values. You need to send those values to mobile app and do the same fetch call you are already using, but replace url with the one generated on backend and add all key-values to FormData.
Example for node backend would look like this
import AWS from 'aws-sdk';
...
const client = new AWS.S3(config);
...
const presignedUrl = client.createPresignedPost({
Bucket: 'example-bucket-name',
Fields: { key: 'example-file-name' },
});
and in mobile app you would
const form = new FormData();
Object.keys(presignedUrl.fields).forEach(key => {
form.append(key, presignedUrl.fields[key]);
})
form.append('file', fileToUpload);
await fetch(presignedUrl.url, {
method: 'POST',
body: form,
headers: {
'Content-Type': 'multipart/form-data'
}
})
My solutions. Please review the sample application. https://github.com/expo/examples/tree/master/with-aws-storage-upload
const response = await fetch(video.uri);
const blob = await response.blob();
const params = {
Bucket: myBucket,
Metadata: {
long: long.toString(),
lat: lat.toString(),
size: videoSize.toString()
},
Key: myKey,
Body: blob
};

PUT form-data axios vue.js

I just updated my User model with "avatar" field so I can upload a photo. I used a PUT method already configured and just added avatar to it. In postman the file upload (form-data) it works just fine, but when trying to upload it using axios from vue.js it doesn't work. I tried in many ways, the last one, I tried to send the request as multi form data.
async saveChanges() {
const fd = new FormData();
fd.append("id", this.$auth.user().id);
fd.append("username", this.$auth.user().username);
fd.append("email", this.user.email);
fd.append("firstName", this.$auth.user().firstName);
fd.append("lastName", this.$auth.user().lastName);
fd.append("isAdmin", this.$auth.user().isAdmin);
fd.append("password", this.user.password);
fd.append("confirmpass", this.user.confirmpass);
fd.append("avatar", this.selectedFile, this.selectedFile.name);
fd.append("_method", "put");
try {
await this.axios.put(`/users/${this.$auth.user().id}`, {
fd
}).then((res) => {
console.log(res);
});
} catch (err) {
console.error(err);
}
}
After i choose the file, it is available, but I am unable to send it trough my method. Should i create another request just for updating the avatar or is it possible to solve this?
Try this
axios.put('/users/${this.$auth.user().id', fd, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
Pass your method as post method and define put in form data
formData.append('_method', 'PUT') .
async handleSubmit() {
let formData = new FormData();
formData.append('image', this.file);
formData.append('title', this.form.title);
formData.append('_method', 'PUT')
try {
const response = await axios.post(`image-update/${this.$route.params.id}`, formData)
this.$router.push('/');
console.log(response);
} catch (e) {
this.error = 'Something error found !';
}
}
My previous wrong code that return empty result in $request->all()
let data = new FormData()
data.append('message', 'AnyMessage')
Then I change it as follows and it's working fine -
let data = "message=AnyMessage"

how to attach a file to request so that it shows up as request.files in python

The way I have found examples are:
const file = fs.readFileSync(filePath)
const formData = new FormData()
formData.append('userId', userId)
formData.append('file', file)
const options = {
method: 'post',
url: 'http://localhost:5000/uploadFile',
headers: {
'content-type': 'multipart/form-data'
},
data: formData
}
await axios(options).then(res => { console.log(res) }).catch(err => { console.log(err) })
But this doesn't attach the file in request.files which is required for python. Since it doesn't attach it as file, the information about file type is also lost.
I have also tried using the following. It does attach the file to request.files but the contents are not of the proper file and all I get is a text string which assumingely is a buffer string output.
const file = new File(fs.readFileSync(filePath), fileName, { type: 'text/csv' })
The aim is to preserve the file type information so that server can save the file properly. What am I missing?
Note that the requests are not sent from nodejs (which has file access) directly.

Categories