Unable to upload a file using Vue frontend and laravel server - laravel

I am trying to upload a file (File can be anything i.e. an image or pdf or doc, absolutely anything) . For that, I made a test form into my Vue component that is below
<form class="mt-5" method="post" enctype="multipart/form-data" id="uploadForm">
<div class="form-group">
<input type="file" id="test" name="test" class="form-control">
</div>
<button #click.prevent="uploadFile" type="button" class="btn btn-sm btn-primary">Upload</button>
</form>
Now when I submit form (click the upload button), I am running a function below
uploadFile() {
let something = $('#test').prop('files')[0];
console.log(something);
let form_data = new FormData();
form_data.append('file', something);
console.log(form_data);
axios.post('/upload/file', { form_data })
.then(() => {
console.log("done");
})
},
So when I console.log(something), it shows me the info of uploaded file but when I send data to server using axios and dd($request->all()) there, it shows me something => [] an empty array, that means, I am not getting the file and hence cant process it further to save it into my folders (upload).
What am I doing wrong here?

This happens because you are not setting the header Content-Type as multipart/form-data (and by default the application/json is being used) when making the request with axios, and the enctype attribute has no effect, since your not using the default form submit action. So try to pass a third argument in the post method, specifying the correct Content-Type header.
const uploadAvatar = ({ id, file }) => {
const formData = new FormData();
formData.append('avatar', file);
return axios.post(`users/${id}/avatar`, formData, {
headers: { 'Content-Type': 'multipart/form-data' },
});
};

Related

How to send by form an image in http request, and with what headers?

I searched on google and nothing...
i have a form in my view on vueJS :
<form #submit.prevent="avatar()" method="POST" enctype="multipart/form-data">
<input type="file" name="profilePicture" id="profilepicture" >
<button type="submit">Valider mon avatar?</button>
</form>
The user send an image.
My question is,
i want to send the image (sending by user with the form) in a function, and this function send the image to Http Request in headers ...
the api request begin with :
app.post('/myupload/:iduser', async (req, res) => {
try{
var { iduser } = req.params ;
const { image } = req.file ;
[...]
my function in my view on vuejs is actually :
async function avatar() {
console.log(document.getElementById("profilepicture").value);
// for having the image sending src
let response = await fetch(`http://localhost:196/myupload/${MyTokenStore.myid}`, {
method: "POST",
headers: {
"Content-Type": "multipart/form-data",
},
body: JSON.stringify(document.getElementById("profilepicture").value)
})
.then((response) => response.json())
.catch((error) => {
console.log("Failed", error)
});
if(response.error){
alert(response.message);
return
}
}
But the only parameter i make in request is the string of the src image, and the error servor is :
TypeError: Cannot destructure property 'image' of 'req.files' as it is undefined.
Please, i need help, the request run when I go directly to the url of the request (but the browser directly displays the server response):
<form :action="`http://localhost:196/myupload/${MyTokenStore.myid}`"
method="POST" enctype="multipart/form-data">
<input type="file" name="image"/>
<button type="submit">Valider mon avatar</button>
</form>
but I fail to put it in a function...
thank you.
To send an image from Vue doing a request you have to use a FormData object. For example:
/**
* #description - register user
*/
const register = async () => {
try {
const fd = new FormData();
Object.keys(user.value).forEach((key) => {
fd.append(key, user.value[key]);
});
const res = await axios.post('/register', fd, {
headers: {
'Content-Type': 'multipart/form-data',
},
});
toast.success(res.data);
} catch (err) {
console.log(err);
toast.error(err.response.data);
}
};
In the previous code, in register I'm using a FormData to send the user object to the backend. Previously, you should set it. I made it like the following example:
const setProfileImage = (e) => {
image_preview.value = URL.createObjectURL(e.target.files[0]);
document.getElementById('image_preview').style.height = '150px';
document.getElementById('image_preview').style.width = '150px';
user.value.profile_image = e.target.files[0]; // this is important for you.
user.value.image = e.target.files[0].name;
};
setProfileImage is receiving an event from an Input file. If you see the comment I write in the code, user.value.profile_image = e.target.files[0] is the entire file. The rest is to display the image and send the name to store into the database.
<div class="mb-3">
<label
for="profile_image"
class="bg-primary text-white rounded-3 text-center w-100 p-2 profile_image"
>
Seleccione su foto de perfil <i class="ps-1 bi bi-card-image"></i>
</label>
<input
type="file"
class="form-control d-none"
id="profile_image"
placeholder="Adjunte su foto de perfil"
#change="setProfileImage"
/>
</div>
This is the Input file what I was talking. The event is an #change to catch correctly the file.
Hope it works for you.

Problem sending file as FormData to GraphQL HotChocolate server using fetch-api

I am trying to send form data to a graphql server using fetch-api
<div>
<!-- HTML5 Input Form Elements -->
<h4>GraphQL API Upload Test</h4>
<input id="fileUpload" type="file" name="fileUpload" />
<input id="fileDetail" type="text" name="fileDetail" />
<button id="upload-button" onclick="uploadFile()"> Upload </button>
<!-- Ajax JavaScript File Upload Logic -->
<script>
var queryTest = `mutation Header($input: Upload!) {
testUploadMutation( file: $input) {
response
}
}`;
async function uploadFile() {
let img = {};
img.file = fileUpload.files[0];
let formData = new FormData();
formData.append("operations",JSON.stringify( { query: queryTest}));
formData.append('map', { "0": ["variables.input"] });
formData.append('0', img.file);
await fetch("/graphql/", {
method: "POST",
body: formData
}).then(response => response.json()).then(data => console.log(data));
}
</script>
</div>
but I keep getting "Invalid JSON in the map multipart field; Expected type of Dictionary<string, string[]> from the server even though the mutation works fine on Banana Cake Pop. I have been using fetch-api to run all other queries and mutation successfully.
This is only code using formData with fetch-api for file upload and its not working . Anybody know what's going on?
Mutaion on Banana Cake Pop
mutation Header($input: Upload!) {
testUploadMutation( file: $input) {
response
}
}
#variables sent using the Banana Cake Pop Variables feature
{
"input": "somefile.jpg"
}
I have also tried sending formData.append('0', img)
instead of formData.append('0', img.file) but the same error

Upload File, file path null, VueJs / Laravel

I try to create a simple file upload with Vuejs and Laravel. But my 'file' variable it seems to be null on post.
<b-form-group label-for="file">
<b-form-file
v-model="file"
id="file"
:state="Boolean(file)">
</b-form-file>
</b-form-group>
data() {
return {
file: null,
},
}
and a method for post . (that works for the rest of the form)
addContract(newContract) {
post("/contracts/" + `${this.customer_id}`, newContract)
.then((response) => {
//
}
.catch(error){
//
}
}
Controller
//code
$fileName = time(). '.' .$request->$file->getClientOriginalExtention();
$request->file->move(public_path('upload'), $fileName);
dd($fileName);
//code
UPDATE
I set the axios header, but now I got error 422, when it was application I didn't but it still didn't work.
headers: {
'Content-Type': 'multipart/form-data'
}
In order for the file to upload via native browser submit, you must provide a name for the file input (along with adding enctype="multipart/form-data" to the enclosing <form> element).
<b-form-file
v-model="file"
id="file"
name="file"
:state="Boolean(file)">
</b-form-file>
This is the same requirement for any form <input>, <select>, or <textarea> control.

File Upload with Ajax And Spring Secruity

After upgrading Spring Security to the 3.2.x version, the Ajax file upload function in my application is no longer working. Based on the SS 3.2 documentation, I append ${_csrf.parameterName}=${_csrf.token} on the ajax URL. That doesn't help. I also try SS post method setting as the followings without any luck either.
var token = $("meta[name='_csrf']").attr("value");
var header = $("meta[name='_csrf_header']").attr("value");
//...
$(document).ready(function() {
new AjaxUpload('#uploadButton', {
action: "/shop/admin/products/images/upload",
name: 'uploadData',
beforeSend : function(xhr) {
xhr.setRequestHeader("Accept","application/json");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader(header, token);
},
onSubmit: function(file , ext) {
this.disable();
if (! (ext && /^(jpg|png|jpeg|gif|JPG|PNG|JPEG|GIF)$/.test(ext))){
alert('Error: invalid file extension');
return false; // cancel upload
}else {
// change button text, when user selects file
button.text(msg);
// If you want to allow uploading only 1 file at time,
// you can disable upload button
this.disable();
// Uploding -> Uploading. -> Uploading...
interval = window.setInterval(function(){
var text = button.text();
if (text.length < 13){
button.text(text + '.');
} else {
button.text(msg);
}
}, 200);
}
},
onComplete: function(file, response) {
button.text(msg);
window.clearInterval(interval);
this.enable();
}
});
});
And a html related code:
<button id="uploadButton" type="button" class="btn btn-default" th:text="#{label.upload}"></button>
The other option mentioned in the SS documentation is a filter configuration order. The Java configuration of the application doesn't come with any filter configuration. So this option can't be applied.
How to deal with this problem?
According to the latest Spring Security documentation, the code should be $("meta[name='_csrf']").attr("content") instead of $("meta[name='_csrf']").attr("value") which seems to make sense because the HTML meta tag has a content attribute instead of a value attribute.
Could you make this change and try again?
A normal form, but note the hidden CSRF:
<form id="myForm" action="upload" method="post">
<input type="file" name="file">
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}">
<input type="submit" value="Upload file!">
</form>
Ajaxify with jQuery Form Plugin:
$(document).ready(function() {
$('#myForm').ajaxForm(function() {
alert("File was uploaded!");
});
});
Last step for success: Make sure you have MultipartFilter before Spring Security in your web.xml, as described in Spring Security reference, section CSRF Caveats.
jQuery Form Plugin has different strategies for file upload depending on browser, but the above should work regardless.

ASP.NET MVC 3 - File upload through AngularJS

I'm using AngularJS with my pages, and I have a doubt: when I do post with my form, how can I pass some selected file to my ASP.NET MVC 3 Controller?
Check this out:
My form:
<form enctype="multipart/form-data" ng-controller="FilesController" ng-submit="submitingForm()">
<div>
Choose the file:
<input type="file" onchange="angular.element(this).scope().setSelectedFile(this)" />
</div>
<input type="submit" value="Confirm" />
</form>
And the AngularJS Controller:
var module = angular.module('application', []);
(function (ang, app) {
function FilesController($scope, $http) {
$scope.setSelectedFile = function (element) {
$scope.$apply(function($scope) {
$scope.selectedFile = element.files[0];
});
};
$scope.submitingForm = function() {
$http.post(url, ???????).success(function() {
// How to pass that selected file for my ASP.NET controller?
});
}
}
app.controller("FilesController", FilesController);
})(angular, module);
Thank you!!!
I am not quite familiar with AngularJS but if you are attempting to upload a file using an AJAX request you can forget about it. That's not something that could be done. You could use the HTML5 File API if you want to upload files asynchronously to the server. There's an entire section dedicated to this.
And if your client browsers do not support the HTML5 File API you could use a File Upload plugin such as FineUploader or Uploadify (there are quite many others, just google).
My Approach is to use FormData.
Create a input tag like this.
<input id="imgInp" type="file" aria-label="Add photos to your post" class="upload" name="file" onchange="angular.element(this).scope().LoadFileData(this.files)" multiple="" accept="image/*" style="margin-top: -38px; opacity: 0; width: 28px;">
And in your Angular Controller create a method LoadFileData(inputFiles) as bellow:
var formData = new FormData();
$scope.LoadFileData = function (files) {
for (var file in files) {
formData.append("file", files[file]);
}
};
Now in formData variable you will have the uploaded files. Just send it to asp.net mvc controller.
$scope.submit = function () {
$http.post("/YourController/Method", formData, {
withCredentials: true,
headers: { 'Content-Type': undefined },
transformRequest: angular.identity
}).success(function (response) {
}
In Server side, Asp.NET MVC 4 controller you will have the files
var files = Request.Files;

Resources