Simple async image upload for Express? - javascript

I'm using a button click to trigger a file input dialog. Once the file is selected, I'm displaying the thumbnail in a preview.
const uploadListener = function() {
const preview = document.getElementById('preview')
const uploadBlob = window.URL.createObjectURL(this.files[0])
preview.style.backgroundImage = `url(${ uploadBlob })`;
}
const fileUploader = document.getElementById('fileUpload')
fileUploader.addEventListener('change', uploadListener)
From here, what's the easiest way to get the file at uploadBlob asynchronously sent (via XMLHttpRequest()?) to my node.js Express server and saved to the server?
I've written this out with a base64 encoded FileReader() in the past, where you have to filter out the metadata, then decode to a binary file and figure out the name + extension on the server, but it was slow and seemed sort of obscure.

It's misleading to name the variable uploadBlob since it's not a blob any more. it's a url, you don't send that to the server.
Basically, append the blob/file to a FormData, then send the formdata in your ajax request
const fd = new FormData()
fd.append('avatar', this.files[0])
// fd.append('avatar', this.files[0], optionalFileName)
fetch(uploadUrl, {method: 'post', body: fd})
/*
or using XMLHttpRequest:
var xhr = new XMLHttpRequest
xhr.open('POST', uploadURL)
xhr.send(fd)
*/

Related

Is it possible to read object from AJAX request on server side?

Actually, I'm trying to send video file in base64 but it the file is large (small files works fine) that's why ajax process not completed and I got 400 error.
So, I thought to send a file object like below so, I can read this object from the server-side. But I don't know if it is possible? OR is there any way through which I can handle large video file upload?
[object FileReader]
And here is my AJAX Code
var reader = new FileReader();
// this function is triggered once a call to readAsDataURL returns
reader.onload = async function(event){
var fileData = new FormData();
var fileType;
fileType = ".avi";
// console.log(my_script_vars.postID);
// fileData.append("file", event.target);
fileData.append("file", event.target.result);
fileData.append("action", "myaction");
fileData.append("filetype", fileType);
fileData.append("post_id", my_script_vars.postID);
jQuery.ajax({
url: 'https://www.reelme.app/sign-up/wp-admin/admin-ajax.php',
processData: false,
contentType: false,
cache: false,
data: fileData,
type: 'POST',
.......
.......
.......
});
}
Please help. Thanks in advance.
You shouldn't read the file into base64 and store everything in memory. screw that FileReader you have.
you are doing the right thing by using FormData, but a FormData can also append blob & files
// Simulate a file you would normally get from a file input or drag n drop
const file = new File(['abc'], 'sample.txt', { type: 'text/plain' })
const fd = new FormData()
fd.append('file', file)
then to upload it i would suggest that you use fetch instead of jQuery that requires all those processData & other config
const url = 'https://www.reelme.app/sign-up/wp-admin/admin-ajax.php'
fetch(url, { method: 'POST', body: fd })
.then(console.log, console.error)
JSON isn't meant to handle large binary data... b/c it's no good streaming format.

JavaScript - Axios POST request empty form data (request payload)

I have a Vue.js app which uses axios to interact with a Laravel API. I'm trying to make a POST request with an image file in it to upload in the backend.
The issue I'm having is that axios makes the POST request with empty payload.
I've tried sending it both as a plain JS object and with FormData. In both cases the request payload is empty. I've looked on the internet for hours but I was unable to find anything while trying to tackle the issue in the past few days...
This is how I make the request:
let fd = new FormData();
fd.append('file', this.file);
console.log(...fd) //shows the file is there with its data
axios
.post("/api/images", fd)
.then(response => {
//Handle success
})
.catch(errors => {
//Catch errors
});
This is how I get the file from the form:
let selectedImage = this.$refs.fileInput.files[0];
const reader = new FileReader();
reader.addEventListener('load', (event) => {
this.file = event.target.result;
});
reader.readAsDataURL(selectedImage);
I've tried experimenting with the request headers and at the moment they are as follows:
"Accept" : "application/json",
"Content-Type": "multipart/form-data; charset=utf-8; boundary=" + Math.random().toString().substr(2),
"Authorization": "Bearer " + this.user.api_token,
"X-CSRF-TOKEN": document.querySelector('meta[name="csrf-token"]').content
The responses from Laravel are always that the file is required (as expected when it's indeed missing).
I did try encoding the file in Base64 but I have trouble validating that it's an image in the backend.
I found this similar question but it wasn't of any help: FormData sends empty data using axios
I want to send a file + JSON data but I'm ok with just making the file upload work. So... How do I send a file from Vue.js app to Laravel API using Axios? What am I doing wrong?

How to capture uploaded file in post request to Google Apps Script?

I am trying to build a script to save data (text + image + pdf) from an HTML form (NOT Google Form).
I have the following function to upload a file:
function upload(x) {
var destination_id = 'folder_id'
var destination = DriveApp.getFolderById(destination_id)
var contentType = 'image/png'
var img = x.getAs(contentType)
destination.createFile(img)
}
Inside my doPost function I am calling the above upload function like this:
upload(e.parameter.img)
I have an input of type file with a name and id of img. I also have the following event listener to prepare the body of the POST request:
form.addEventListener('submit', e => {
e.preventDefault()
let fd = new FormData(form)
fetch(scriptURL, { method: 'POST', body: fd})
.then(response => console.log('Success!', response))
.catch(error => console.error('Error!', error.message))
})
When I submit my form, my text gets saved, but the file is not uploaded. I do not see any errors in the console either. What am I doing wrong? Is there an easier alternative to uploading form data to Google Drive?
type=file don't seem to be currently supported. You can workaround this using FileReader api on the client side to convert file data to a base64 encoded websafe string and send the data as string or a byte array.
Related answer

Converting data of content type 'application/java-archive' into blob object

I have one GET request which returns a JAR file, which I need to download.
Easiest way to to the downloading part is to let browser handle the downloading part as follows :
window.location.href = URL
But, that does not work for error handling (handling server errors).
Alternatively, I found another way which creates blob object, and creates Object URL from that object and assigns it to anchor tag for downloading -
callSomeURL().then((res) => {
const blob = new Blob([res._body], { type: res.headers.get('content-type')
});
const url = window.URL.createObjectURL(blob);
const linkElement = document.createElement('a');
linkElement.setAttribute('href', url);
linkElement.setAttribute('download', 'test jar file');
const clickEvent = new MouseEvent('click', {view: window});
linkElement.dispatchEvent(clickEvent);
}).catch((error) => error handling part)
content type is 'application/java-archive'
res._body is encoded string.
Problem with this is that the file downloaded is invalid / corrupt. (Not sure whats wrong with the implementation).
I have 2 questions here -
What is the proper way to create a blob object? Is it created using the encoded data that the response returns or the URL of the request?
What is the proper way to handle file download with error handling?
Your problem is that the response you get is plain/text.
So when you generate your Blob, it's still plain text, and the binary data got mangled when converted to utf16 by javascript.
To avoid that, you can request it as a blob directly from your ajax call.
With XMLHttpRequest, you can set the responseType parameter of your XHR object:
var xhr = new XMLHttpRequest();
xhr.open('get', your_url);
xhr.responseType = 'blob';
xhr.onload = function() {
var blob = xhr.response;
// do something with the blob
var url = URL.createObjectURL(blob);
anchor.href = url
anchor.click();
};
xhr.send();
With fetch API, you can call the blob() method of the Response object
fetch(your_url)
.then(resp => resp.blob())
.then(doSomethingWithBlob)

Sending a file stream in JSON

Can I send the stream of data from a File or Blob and post it in JSON in Angular 5?
I tried using a FileReader, but not able to get the stream out of it using the
result property.
let blobfile=new Blob([this.curResume]);
let fr=new FileReader;
fr.readAsText(blobfile);
console.log(fr,fr.result);
This is how I've tried it and this is what I get in the console.
console output
I understood that you are trying to push a file to the server using POST API call. In that case you can pass it as formData.
Please be a little eloborate on adding your question.
const fileData= new Blob([this.yourFile], { type: "<your File type>" });
const formData = new FormData();
formData.append("yourFile", fileData);
this.httpClient.post(<your url>, formData);

Categories

Resources