Vuejs won't send correct data - javascript

I have image field, when I change the image it does change the image and before I send it to back-end I can see the values are correct, but sent data values are empty!
Code
Commented
save_changes() {
/* eslint-disable */
if (!this.validateForm) return;
console.log("image: ", this.data_local.image); // new image data are present
this.$http
.put(
"/api/admin/posts/meta/" + this.$route.params.id,
this.data_local, // new image data is empty!
{
headers: {
Authorization: localStorage.getItem("access_token"),
},
}
)
.then((res) => {
}
//rest of it...
},
update_avatar(event) {
this.dialogVisible = true;
this.dialogImageUrl = URL.createObjectURL(event.target.files[0]);
this.data_local.image = event.target.files[0]; // this is where I sent selected image and pass it to my `data_local` array objects
},
Screenshots
Any suggestions?
Update
header request

What you can try is to send it as an FormData
let file = this.data_local.image
let image = URL.createObjectURL(file)
let formData = new FormData();
formData.append("image", image);
formData.append("id", 71);
formData.append(....)
this.$http
.put(
"/api/admin/posts/meta/" + this.$route.params.id,
formData,
{
headers: {
Authorization: localStorage.getItem("access_token"),
},
}
)
.then((res) => {
}
The headers should look something like this:
Your image should have this (binary)

Related

Uploaded file is corrupt

I'm trying to upload a cropped image via client using fetch. The upload process works, the file size seems to be correct too but the uploaded image is corrupt and appears to be a white 16x16 square on the server. The file won't open when I download it (damaged or corrupt). I'm struggling to understand what I'm doing wrong. The back-end is Drupal.
Uploading files directly from an input using the same postFile function works without a problem.
const toFile = (blob) => {
blob.lastModifiedDate = new Date();
blob.name = 'cropped.png';
return blob;
}
const onCropperCrop = () => {
const imageElement = cropperRef?.current;
const cropper = imageElement?.cropper;
cropper.getCroppedCanvas().toBlob((blob) => {
const file = toFile(blob);
onCrop(file);
});
};
const onCrop = (file) => postFile(params);
export const postFile = async (
_file,
_uri,
_xcsrf_token,
_accessToken,
) => {
let formData = new FormData();
formData.append('File', _file);
let headers = {
headers: {
Accept: 'application/hal+json',
'Content-Type': 'application/octet-stream',
'Content-Disposition': 'file; filename="' + _file.name + '"',
'X-CSRF-Token': _xcsrf_token,
Authorization: 'Bearer ' + _accessToken,
},
};
return await fetch(_uri, {
method: 'POST',
headers: headers,
body: formData,
credentials: 'include'
});
};
The file object:

Display image from API

I got problem how to display image send by API from backend it not display. And when I console.log, I got this error.
This is my code as your reference.
HTML
<img [src]="imageToShow" style="width:100%;margin-left: -14px;">
Component
ngOnInit() {
this.getBanner()
}
getBanner() {
this.bannerId = {
confId: 1,
type: "Banner",
};
this.httpService.getBanner(this.bannerId).subscribe(
(baseImage: any) => {
let objectURL = "data:image/jpeg;base64," + baseImage.image;
this.imageToShow = this.sanitizer.bypassSecurityTrustUrl(objectURL);
},
(error) => {
// this.isImageLoading = false;
console.log(error);
}
);
}
Service
public getBanner(data){
console.log(data)
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
responseType: 'blob',
Authorization: 'Bearer '+this.getToken()
})
};
return this.httpClient.post((this.serverUrl + this.basePath + '/landing/conferenceitem'),data,httpOptions);
}
edit
when I check up Network Response I got this image
Try this
Step #1
Remove Content-Type header and set responseType to blob in httpOptions, but not in the header part like you did. Now, you should get a blob as a response. Before, angular was trying to parse your response as JSON, hence the error
public getBanner(data){
console.log(data)
const httpOptions = {
headers: new HttpHeaders({
Authorization: 'Bearer '+this.getToken()
}),
responseType: 'blob'
};
return this.httpClient.post((this.serverUrl + this.basePath + '/landing/conferenceitem'),data,httpOptions);
}
Step #2 Use baseImage instead of baseImage.image (the response is a blob, it does not have an image property), and then use createObjectURL to get an image url from the blob. Sanitize that URL like your did
this.httpService.getBanner(this.bannerId).subscribe(
(baseImage: Blob) => {
let objectURL = URL.createObjectURL(baseImage);
this.imageToShow = this.sanitizer.bypassSecurityTrustUrl(objectURL);
},
(error) => {
// this.isImageLoading = false;
console.log(error);
}
);
One way to fix this is by Setting the response type to blob
const requestOptions: Object = {
/* other options here */
responseType: 'blob'
}
return this.httpClient.post((this.serverUrl + this.basePath + '/landing/conferenceitem'),data,requestOptions);
and you have to convert your image data to a dataURL:
this.httpService.getBanner(this.bannerId).subscribe(
(baseImage: any) => {
this.imageToShow = baseImage;
},
(error) => {
// this.isImageLoading = false;
console.log(error);
}
);
Change Your getBannerMethod as below :-
getBanner() {
this.bannerId = {
confId: 1,
type: "Banner",
};
this.httpService.getBanner(this.bannerId).subscribe(
(baseImage: any) => {
const reader = new FileReader();
const url = reader.readAsDataURL(baseImage.image);
reader.onloadend = () => this.imageToShow = reader.result;
},
(error) => {
// this.isImageLoading = false;
console.log(error);
}
);
}
Working Stackblitz :- https://stackblitz.com/edit/angular-yvicvq

antd upload api: how to return promise

I am working with antd framework and I have to use upload API.
This is the signature:
action: Uploading URL : string|(file) => Promise
I am invoking the API in this way trying to return a Promise:
<Upload {...propsUpload}>
<Button> <Icon type="upload" />Upload</Button>
</Upload>
with propsUpload that refers to function uploadMedia
const propsUpload = {
action: this.uploadMedia,
listType: 'picture',
defaultFileList: [],
className: 'upload-list-inline',
};
and this is the function uploadMedia
uploadMedia = (file) => {
let formData = new FormData();
formData.append('file', file);
formData.append('uuid', this.generateuuid());
formData.append('domain', 'POST');
formData.append('filename', file.name );
return fetch(process.env.REACT_APP_API_URL +
'/v100/media/upload', {
method: 'POST',
credentials: 'include',
headers: {
Accept: 'application/json'
},
body: formData
})
.then(response => response.json())
.then(data => data.data)
.catch(error => {
console.log('Error fetching profile ' + error)
})
}
The file is uploaded to server correctly.
But after the call to API, antd try to do another call that fails, maybe because I am not returning the correct value from function.
As result the thumbnail is displayed with red border and and error is shownd. In the image below there are both (the call that fails and image with red border)
What type of object I have to return in function uploadMedia to use api correctly?
Thanks
I haven't used antd but looking at the docs of Uplaod component I think you're using it wrong. Look at the examples there and see the code, action expects either a URL or a Promise that will return this URl. And Upload in this case will make request itself, so you don't need to do fetch. And your promise returns the data (object) so the Upload sends the request to [object Object] (which is what's returned by .toString() when applied to an object in JS)
EDIT
Try to check all examples in docs, I can see that there is an example when you want to manually upload the file (if you really need it)
For anyone looking to access the response object after calling the API. There are two ways you can get access to the response.
Implement a custom API request mentioned as in other answers for this question.
Use the onChange method provided by AntD (Which is the easier than utilizing the custom request)
I will explain the second approach below using a code block.
const fileUploadProps = {
name: "file",
action: config.remote + "api/file",
method: "POST",
showUploadList: false,
headers: {
authorization: "authorization-text",
contentType: "multipart/form-data"
},
onChange(info) {
if (info.file.status === "done") {
const { response } = info.file;
updateProfile(response.payload.file);
} else if (info.file.status === "error") {
message.error("Error uploading the file");
props.endLoad();
}
},
beforeUpload(file) {
const isJpgOrPng = file.type === "image/jpeg" || file.type === "image/png";
if (!isJpgOrPng) {
message.error("You can only upload JPG/PNG file!");
}
const isLt2M = file.size / 1024 / 1024 < 2;
const isGT20K = file.size / 1024 > 20;
if (!isLt2M) {
message.error("Image must smaller than 2MB!");
}
if (!isGT20K) {
message.error("Image must larger than 20KB!");
}
if (isJpgOrPng && isLt2M && isGT20K) {
props.startLoad();
return true;
} else {
return false;
}
}
};
In Render function I have the AntD upload component
<Upload {...fileUploadProps}>
<Button icon={<CameraFilled style={{ fontSize: "30px" }} />}></Button>
</Upload>
You can notice how I got the access to the response object inside onChange function.
Once the upload is complete it will call the onChange function having response object inside the info object.
So from there you can get access to your data object easily and call the next method.
I solved using api customRequest in this way:
uploadMedia = (componentsData) => {
let formData = new FormData();
formData.append('file', componentsData.file);
formData.append('uuid', this.generateuuid());
formData.append('domain', 'POST');
formData.append('filename', componentsData.file.name );
fetch(process.env.REACT_APP_API_URL + '/v100/media/upload', {
method: 'POST',
credentials: 'include',
headers: {
Accept: 'application/json'
},
body: formData
})
.then(response => response.json())
.then(data => data.data)
.then(data=> componentsData.onSuccess())
.catch(error => {
console.log('Error fetching profile ' + error)
componentsData.onError("Error uploading image")
})
}
For those who are not clear how to actually implement it (and it is unclear in docs):
Just implement a customRequest function in the props that accepts two callbacks, which are onError and onSuccess, and other data such as file and filename.
Like this
const props = {
customRequest: (componentsData) => {
let formData = new FormData();
formData.append('file', componentsData.file);
formData.append('uuid', this.generateuuid());
formData.append('domain', 'POST');
formData.append('filename', componentsData.file.name );
fetch(process.env.REACT_APP_API_URL + '/v100/media/upload', {
method: 'POST',
credentials: 'include',
headers: {
Accept: 'application/json'
},
body: formData
})
.then(response => response.json())
.then(data => data.data)
.then(data=> componentsData.onSuccess())
.catch(error => {
console.log('Error fetching profile ' + error)
componentsData.onError("Error uploading image")
})
}
}
And let Upload component receive the props.
const App = () => {
return <Upload {...props} />
}

Is it possible to send data and files in the same request?

I have an API that receives uploads of APP files and images
To send from APP to the API I use fetch
const data = new FormData();
let i = 0;
export const dataPush = (fileUri, fileType, fileName) => {
data.append('file'+i, {
uri: fileUri,
type: fileType,
name: fileName
});
i++;
};
export const uploadFiles = () => {
console.log(data);
fetch('http://192.168.0.23/apiapp/public/api/annex', {
method: 'post',
body: data
}).then(res => {
console.log(res)
});
}
But I'd like to send in the same request data obtained from a form
But I did not find a way to do it, always or just send the data, or just send the files
Is it possible to send everything in the same request? And if possible, how?
You just append whatever data that you desire that isn't file data to the FormData object.
data.append("not_a_file", "This is a string");
I did so based on Quentin's response and it worked
const formData = new FormData();
const i = 0;
export const filePush = (fileUri, fileType, fileName) => {
formData.append('file'+i, {
uri: fileUri,
type: fileType,
name: fileName
});
i++;
};
export const dataPush = (name, content) => {
formData.append(name, content);
};
export const uploadFiles = () => {
fetch('http://192.168.0.23/apiapp/public/api/annex', {
method: 'post',
body: formData
}).then(res => {
console.log(res._bodyText)
}).catch(error => {
console.log(error.message)
});
}

Javascript/React fetch api sending image via formdata

I'm trying to send a file object (image) as a multipart/form-data request using the javascript fetch api.
The code below shows how I convert the file object to string format.
The image parameter is an array of File objects. I want to send the first image of that array to a webservice.
onImageUpload = ((image) => {
//File to arraybuffer
let fr = new FileReader();
fr.onload = function(e) {
var text = e.target.result;
AccountService.uploadProfileImage(localStorage.getItem('session-key'), text)
.then((ro) => {
if(ro.code == 200) {
this.showSnackbar("Profile image uploaded successfully!");
}
else {
this.showSnackbar("Error uploading your image. Please try again later.");
}
})
}
fr.readAsText(image[0]);
})
Below is my uploadProfileImage function, which makes the post request using the fetch api.
static async uploadProfileImage(sessionKey, image) {
var reader = new FileReader();
let ro = new ResponseObject();
let fd = new FormData();
let imgObj = new Image();
imgObj.src = image;
let blob = new Blob([new Uint8Array(image)], { type: "image/jpg"});
fd.append("name", localStorage.getItem('username'));
fd.append("file", blob);
return new Promise((resolve, reject) => {
fetch(UrlConstants.BASE_URL + this.urlUploadProfileImage, {
method: "POST",
headers: {
'Authorization': 'Bearer ' + sessionKey,
"Content-type": "multipart/form-data;"
},
body: fd
}).then((response) => {
ro.code = response.status;
return response.text();
})
.then((text) => {
ro.message = text;
resolve(ro);
})
.catch((ex) => {
reject(ex);
})
});
}
When I sent the image parameter in the uploadProfileImage without converting it into a blob the data are being sent, but i need the blob to have the Content-Type: "image/jpg" in the request as the api I'm working with can't handle the request without it.
The problem that the image is not being included in the request.
How can I do that?
Thanks for your help.

Categories

Resources