可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
In angular 5 I am getting the images for hotelgallery from mongodb through my service. So basically the data what I am getting is like this
{
fieldname: "hotelgallery",
originalname: "e.jpg",
encoding: "7bit",
mimetype: "image/jpeg",
destination: "./public/",
encoding : "7bit",
filename : "1521139307413.jpg"
mimetype : "image/jpeg"
path : "public/1521139307413.jpg"
size : 66474
}
{
fieldname: "hotelgallery",
originalname: "e.jpg",
encoding: "7bit",
mimetype: "image/jpeg",
destination: "./public/",
encoding : "7bit",
filename : "1521139307413.jpg"
mimetype : "image/jpeg"
path : "public/1521139307413.jpg"
size : 66474
}
{
fieldname: "hotelgallery",
originalname: "j.jpg",
encoding: "7bit",
mimetype: "image/jpeg",
destination: "./public/",
encoding : "7bit",
filename : "1526753678390.jpg"
mimetype : "image/jpeg"
path : "public/1526753678390.jpg"
size : 66470
}
{
fieldname: "hotelgallery",
originalname: "k.jpg",
encoding: "7bit",
mimetype: "image/jpeg",
destination: "./public/",
encoding : "7bit",
filename : "7865456789413.jpg"
mimetype : "image/jpeg"
path : "public/7865456789413.jpg"
size : 66300
}
Now I want to again append those data to FormData but its not working.
The code what I have done so far
export class HotelEditComponent implements OnInit {
formData = new FormData();
ngOnInit() {
this.getOneHotel(this.route.snapshot.params['id']);
}
getOneHotel(id) {
this.http.get( this.apiUrl + '/api/hotel/' + id).subscribe(data => {
this.hotel = data;
this.appendImages(data['hotelimages']); //Here I am getting the data as mentioned here
});
}
public appendImages(imagedata) {
for (var i = 0; i < imagedata.length; i++) {
console.log(imagedata[i]);
this.formData.append('hotelgallery', imagedata[i], imagedata[i]['originalname']);
}
console.log(this.formData);
}
}
So can someone tell me how can I append the existing image data to FormData? Any help and suggestions will be really appreciable.
UseCase for this:
Actually I had used formData to upload images in angular. Now in the edit page the images are showing fine. But lets say a user edits some data and upload some images or remove some images. In that case I am getting the images from the database and again trying to upload them with formdata.
I have used this module and multer for nodejs to upload images with formData.
回答1:
So can someone tell me how can I append the existing image data to FormData? Any help and suggestions will be really appreciable.
Actually, this approach need more add script solution. for example
1. Get Image Blob from server
Since you return detail object of images, not with the blob. You need have a endpoint to return as blob. (or if return as data buffer then it transform to blob you can use BlobUtil)
2. Put Blob to append form data
You need use blob to append in param 2 no a path, see documentation.
name
The name of the field whose data is contained in value.
value
The field's value. This can be a USVString or Blob (including subclasses
such as File).
filename Optional
The filename reported to the server
(a USVString), when a Blob or File is passed as the second parameter.
The default filename for Blob objects is "blob". The default filename
for File objects is the file's filename.
That what you need, but that is bad practice.
Let's say, you have 30 images to edit, then you need request blob endpoint to get those images blob to appends. But user only want to update 1 image, wasting time to request image blob, right?
For edit image usually we don't need append to file form (<input type="file" />
).
Just show it as thumbnail to see what image uploaded and let file form empty.
What we do usually, thumbnail that image.
When user what to change, user put new image and replace old image with new want and update database.
if not, do nothing for image. (YAGNI)
回答2:
FormData's append is silently failing here. You need to attach the 'image' as a blob. See the MDN docs.
formData.append('hotelgallery', new Blob([imagedata[i]], { type: "text/xml"}), imagedata[i]['originalname']);
Also, just printing formData won't show anything, instead try:
console.log(this.formData.getAll('hotelgallery'));
or
for (var value of this.formData.values()) {
console.log(value);
}
回答3:
But lets say a user edits some data and upload some images or remove
some images. In that case I am getting the images from the database
and again trying to upload them with formdata.
So, you can pass object to universal method and on result get formData
. Object data even can contain nested objects.
static createFormData(object: Object, form?: FormData, namespace?: string): FormData {
const formData = form || new FormData();
for (let property in object) {
if (!object.hasOwnProperty(property) || object[property] === undefined) {
continue;
}
const formKey = namespace ? `${namespace}[${property}]` : property;
if (object[property] instanceof Date) {
formData.append(formKey, object[property].toISOString());
} else if (typeof object[property] === 'object' && !(object[property] instanceof File)) {
this.createFormData(object[property], formData, formKey);
}
else if (typeof object[property] === 'number') {
let numberStr = object[property].toString().replace('.', ',');
formData.append(formKey, numberStr);
}
else {
formData.append(formKey, object[property]);
}
}
return formData;
}
}
In Component class:
export class HotelEditComponent implements OnInit {
formData = new FormData();
hotel: any;
...
ngOnInit() {
this.getOneHotel(this.route.snapshot.params['id']);
}
getOneHotel(id) {
this.http.get( this.apiUrl + '/api/hotel/' + id).subscribe(data => {
this.hotel = data;
});
}
postToServer() {
// or even can pass full `this.hotel` object
// this.helperService.createFormData(this.hotel)
this.formData = this.helperService.createFormData(this.hotel['hotelimages'])
this.service.post(this.formData);
}
...
}
回答4:
It looks like you are trying to append a JSON array, since formData.append can only accept a string or blob, try the JSON.stringify() method to convert your array into a JSON string. (untested)
e.g. I think you can replace
this.appendImages(data['hotelimages']);
with
this.formData.append('hotelgallery', JSON.stringify(data['hotelimages']));
回答5:
This is more of a design issue right now, rather then a tech problem. You are asking about posting FormData again and you want to fetch the images data again for that.
Now let's look at your current design.
- User uploads 3 images of 4MB size each
- On your edit page you downloads each of these images. Cost=12MB
- On the edit page user deletes 2 images and adds 2 images. Cost=12MB
- So final cost of updating 2 images of 8MB is 24MB. Which is a lot
Now before figuring out how to do FormData, figure out the right design for your app.
Consider the OLX
site which allows you to post ads and later edit them. When you edit and remove a image, they call a API for removing the image
The ideal design in my opinion would be below
- Submit all images in your create
- For edit create a add and remove endpoint for the image
Submitting text data again on a edit form is ok, but submitting the same images data again on a edit form is never ok. Reconsider your design