Sending cropped image blob with xmlhttprequest to flask server - javascript

Form
<h2 class="uk-modal-title">Change Profile Picture</h2><br>
<form action="{{url_for('upload_dp', username=username)}}" method="POST" enctype="multipart/form-data">
<input type="file" accept="image/*" placeholder="Upload profile picture" onchange="loadFile(event)" id="uploaded" required>
<img id="dp">
<button onclick="beforeSubmit()">Upload</button>
Javascript
var cropper;
function loadFile(image) {
var dp = document.getElementById('dp');
dp.src = URL.createObjectURL(image.target.files[0]);
dp.onload = function() { URL.revokeObjectURL(dp.src)};
cropper = new Cropper(dp, { aspectRatio: 1 });
}
function beforeSubmit() {
cropper.getCroppedCanvas().toBlob((blob) => {
var formData = new FormData();
formData.append("dp", blob);
formData.append('username', '{{username|safe}}');
var xhr = new XMLHttpRequest;
xhr.open( "POST", "/upload_dp");
xhr.setRequestHeader('Content-Type', 'multipart/form-data');
xhr.send(formData);
}, "image/jpeg");
}
When an image is uploaded for , it renders and a cropper appears on it. Till here, things work fine.
User, changes cropper according to his need and on pressing button Upload, function beforeSubmit runs where the problem lies. I do not receive any files in the flask application. The request below has non-empty stream and I receive the argument username, but the file dp having cropped image as blob is not received! Please help.
print(request.__dict__)
Is stream the blob file? How are xmlhttprequest with files seen in flask?

Related

Error: Value is not properly formed. Need 3 seperate image uploads on one page?

I have a form where my members can upload three images for their public profiles.
1.card_front, 2.card-back, 3.art_header
I don't want to use "multiple" on an input field as a member can come back to change 1 or all images at anytime, and I need to know which image has been uploaded - front, back or header.
My JS worked for one image upload but not with multiple single files.
My DB (Xano) gives me a 400 error
{
code: ERROR_CODE_INPUT_ERROR,
message: Value is not properly formed.,
payload: {
param: image1}
}
Xano endpoint expects three inputs that I have created (Type: file resource)
image1, image2, image3
(Xano then creates image metadata from a File Resource)
What does "Value is not properly formed" mean and how to fix? OR can anyone suggest a different way to have three seperate image uploads in a form sent to an API using Fetch?
// POST IMAGES
const memberID = localStorage.getItem('MemberID');
console.log("Member ID:", memberID);
const url = 'XANO endpoint';
document.addEventListener('DOMContentLoaded', init);
function init(){
document.getElementById('btnSubmit').addEventListener('click', upload);
}
function upload(ev){
ev.preventDefault();
//create any headers we want
let h = new Headers();
h.append("Accept", "application/json");
h.append("Content-Type", "multipart/form-data");
//bundle the files and data we want to send to the server
let fd = new FormData();
let myFile1 = document.getElementById('cardFront').files[0];
let myFile2 = document.getElementById('cardBack').files[0];
let myFile3 = document.getElementById('artHeader').files[0];
fd.append("member-id", memberID);
fd.append("image1", myFile1);
fd.append("image2", myFile2);
fd.append("image3", myFile3);
let req = new Request(url, {
method: "POST",
headers: h,
mode: "no-cors",
body: fd
});
fetch(req)
.then( (response)=>{
document.getElementById("output").textContent = "Response received from server";
})
.catch( (err) =>{
console.log("ERROR:", err.message);
});
}
<form action="#">
<div>
<input type="hidden" id="nodes_id" data-name="nodes_id" value=`${memberID}`/>
<input type="file" id="cardFront" accept=".png, .jpg, .jpeg"/>
<input type="file" id="cardBack" accept=".png, .jpg, .jpeg"/>
<input type="file" id="artHeader" accept=".png, .jpg, .jpeg"/>
</div>
<div>
<button class="button" id="btnSubmit">Upload Files</button>
</div>
</form>
Your content-type header is missing the boundary, if you remove that header from your code fetch will set it and add the needed boundary for you.

Turn a blob url into a upload file for FormData() and send it via AJAX to a PHP file

I want to convert a blob URL AKA (window.URL.createObjectURL(blob);) into a file object so I can use it with FormData() so I can use that as an upload image file for AJAX but I am not able to do that successfully and I can't find a way to make the blob URL into a file
object for my code situation and I know its possible to do this according to the posts I visited on here it can be done here's one of posts that claim that you can do that How to convert Base64 String to javascript file object like as from file input form? but the reason why I'm not using any of those posts methods because I don't know how to integrate their methods to my code situation or its too complicated to understand.
This is my code that I been working on.
index.php
<script>
document.addEventListener('DOMContentLoaded',function(){
document.querySelector('#image-input').addEventListener('change',createABlobUrlForAImgSrcAndUseThatAsAFileUploadFile);
function createABlobUrlForAImgSrcAndUseThatAsAFileUploadFile(){
//Creating a blob URL
var image_input = document.querySelector('#image-input').files[0];
var file_type= image_input.type;
var blob = new Blob([image_input], { type: file_type || 'application/*'});
var blob_url= window.URL.createObjectURL(blob); //<-Example blob:http://localhost/ed6761d2-2bb4-4f97-a6d8-a35c84621ba5
//
//Form data
var formData= new FormData();
formData.append('blob_url', blob_url);
//
//<AJAX>
var xhr= new XMLHttpRequest();
xhr.onreadystatechange= function(){
if(xhr.readyState == 4){
document.querySelector('#output').innerHTML= xhr.responseText;
//<Allow JS in AJAX request>
var exJS= document.querySelectorAll('#output script');
var enableAll= exJS.length;
for(var i=0; i < enableAll.length; i++){
eval(exJS[i].text);
}
//</Allow JS in AJAX request>
}
}
xhr.open('POST','x');
xhr.send(formData);
//</AJAX>
}
});
</script>
<input id='image-input' type='file'>
<div id='output'></div>
x.php
<?php
$file=$_FILES['blob_url']['name'];
$location='images/'.$file;
move_uploaded_file($_FILES['blob_url']['tmp_name'],$location);
?>
I know my code is not logically correct and I will have to change my code to be able to do what I want to do so I am aware it is not logically correct. Just trying to show you guys what I mean.
This is how I got it done in my project. But in my case, I wanted to convert a blob to a wav file and then send to the back-end.
//Save your blob into a variable
var url = URL.createObjectURL(blob);
//Now convert the blob to a wav file or whatever the type you want
var wavefilefromblob = new File([blob], 'filename.wav');
//Pass the converted file to the backend/service
sendWavFiletoServer(wavefilefromblob);
//This is my function where I call the backend service to send the wav file in Form data
function sendWavFiletoServer(wavFile) {
var formdata = new FormData();
formdata.append("file", wavFile);
var ajax = new XMLHttpRequest();
ajax.addEventListener("load", completeHandler, false);
ajax.addEventListener("error", errorHandler, false);
ajax.addEventListener("abort", abortHandler, false);
ajax.open("POST", "https://yourserviceurl/api/");
ajax.setRequestHeader('API_SECRET', UzI1NiIsInR5cCI6IkpXVCJ9eyLCJleHAiO');
ajax.send(formdata);
}
I think uploading form data should be a blob object, not a blob URL
javascrip:
var image_input = document.querySelector('#image-input').files[0];
var blob_url= window.URL.createObjectURL(image_input);
//Form data
var formData= new FormData();
// ...
// here , content-type: multipart/form-data
formData.append('upload_file', image_input);
php:
$file=$_FILES['upload_file']['name'];
$location='images/'.$file;
move_uploaded_file($_FILES['upload_file']['tmp_name'],$location);
I had the same question and found a way.
This will give you a Blob object:
let blob = await fetch(url).then(r => r.blob());

How to upload a file using javascript?

I want to create an uploader with js. Can anyone help me how to upload a file using javascript?
You can use html5 file type like this:
<input type="file" id="myFile">
You file will be in value:
var myUploadedFile = document.getElementById("myFile").files[0];
For more information see https://www.w3schools.com/jsref/dom_obj_fileupload.asp
and see example here: https://www.script-tutorials.com/pure-html5-file-upload/
You can upload files with XMLHttpRequest and FormData. The example below shows how to upload a newly selected file(s).
<input type="file" name="my_files[]" multiple/>
<script>
const input = document.querySelector('input[type="file"]');
input.addEventListener('change', (e) => {
const fd = new FormData();
// add all selected files
e.target.files.forEach((file) => {
fd.append(e.target.name, file, file.name);
});
// create the request
const xhr = new XMLHttpRequest();
xhr.onload = () => {
if (xhr.status >= 200 && xhr.status < 300) {
// we done!
}
};
// path to server would be where you'd normally post the form to
xhr.open('POST', '/path/to/server', true);
xhr.send(fd);
});
</script>
HTML Part:
<form enctype = "multipart/form-data" onsubmit="return false;" >
<input id="file" type="file" name="static_file" />
<button id="upload-button" onclick="uploadFile(this.form)"> Upload </button>
</form>
JavaScript Part:
function uploadFile(form){
const formData = new FormData(form);
var oOutput = document.getElementById("static_file_response")
var oReq = new XMLHttpRequest();
oReq.open("POST", "upload_static_file", true);
oReq.onload = function(oEvent) {
if (oReq.status == 200) {
oOutput.innerHTML = "Uploaded!";
console.log(oReq.response)
} else {
oOutput.innerHTML = "Error occurred when trying to upload your file.<br \/>";
}
};
oOutput.innerHTML = "Sending file!";
console.log("Sending file!")
oReq.send(formData);
}
In the above HTML, I'm using the form to capture the files and calling the JS function when the button is clicked. In the JS function, I'm using the XMLHttpRequest to send the file.
A detailed step-by-step document can be found here.

How to attach a file with FormData and Blob?

I am trying to attach a file and upload through ajax request. But it creates a new file instead of uploading the file I am trying to provide.
var formData = new FormData();
var blob = new Blob([JSON.stringify({})], {type : 'application/json'});
formData.append("file", blob, "sample.txt");
When I open the file I can see the content getting replaced with {}
Code mentioned will only create and empty form object. If you need to upload that form object to server, use following similar code.
var formElement = document.querySelector("form");
var formData = new FormData(formElement); //reads user input data from form
/**var blob = new Blob([JSON.stringify({})], {type : 'application/json'}); //added {} to form
formData.append("file", blob, "sample.txt"); //names file and keeps {} as content ----not needed**/
var request = new XMLHttpRequest();
request.open("POST", "http://foo.com/submitform.php"); //put ypur end point here
request.send(formData); //send to server
your form html should look something like this
<form enctype="multipart/form-data" method="post" name="submitform">
<label>File to upload:</label>
<input type="file" name="file" required />
<input type="submit" value="Stash the file!" />
</form>
Please read more on this here

Upload photo using Ember addon ember-plupload

I have used ember-plupload for uploading the images.Now I have written a component for this.I am able to open and select the images from my machine.But I am lost what to do next.I have to send the post request to my server endpoint with body params { photo_file: image file }.My code is following.
component.hbs
{{#pl-uploader extensions="jpg jpeg png gif" for="upload-image" onfileadd="uploadImage" as |queue features|}}
<div class="dropzone" id={{dropzone.id}}>
<a id="upload-image">Add an Image.</a>
</div>
{{/pl-uploader}}
component.js
actions:{
uploadImage:function(file){
console.log(file)
let filename = file.get('name');
file.read().then(function (url) {
console.log(filename)
console.log(url)
}
}
I am able to get the file name and encode base64 value.But not sure how to send the request to server endpoint.
http://example.com/api/addphoto and it require body with parameter photo_file and choosed file.
I am able to make the correct request from postman app.In the body of the request ,I am selecting the file option and it directly gives me the option to choose a file from there itself.The request is made successfully and photo gets added to endpoint when I select an image and send request
How should I do it in my app?
You could use an XMLHttpRequest
uploadImage:function(files){
var file = files[0];
var request = new XMLHttpRequest();
request.open('post', "target url", true);
var formData = new FormData();
var fieldName = 'file';
formData.append(fieldName, file);
request.onreadystatechange = Ember.run.bind(this, function () {
if (request.readyState === 4 && request.status !== 0) {
//success
}
});
request.send(formData);
}

Categories