如何将带有表单组值的图像/文件上传到 API? [英] How to upload image/file with formgroup value to API?

查看:22
本文介绍了如何将带有表单组值的图像/文件上传到 API?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

服务做http.post时如何上传图片并添加到表单中?示例产品模块需要名称、价格、封面图像.我尝试使用许多可以从互联网、论坛等获得的方法.但是对这个问题还是一窍不通.

How to upload image and add it to the form when service doing http.post? example product module needs name, price, coverImage. I tried to use many ways that I can get from the internet, forum, etc. But still got no clue about this issue.

我正在使用模型驱动的表单并在选择图像时附加它,我尝试在发送到 API 之前打印出表单的值.console.log 结果的附加图像:

I am using model driven form and append it when image is selected and i tried to print out the values of form before send to API. attached image for console.log result:

仅供参考:我使用的是基于 PHP Laravel 的 API.我试图从$request->file('image');"获取图像

fyi: I am using API based on PHP Laravel. I tried to get the image from "$request->file('image');"

有人可以帮我解决这个案子吗?谢谢.

anybody can help me for this case? thanks.

推荐答案

第 1 部分:通过 FormData 将文件上传到 API

在像 upload.service.ts 这样的服务文件中,您需要创建通过 POST 方法上传文件的函数.下面是这个函数的一个例子:

In your service file like upload.service.ts you need to create function to upload files via POST method. Here is an example for this function:

getUploadHeaders() {
    let headers = new Headers({'Accept': 'application/json'});
    headers.delete('Content-Type');
    return headers;
}    

addNewPost(newPost: FormData): Observable<FormData> {
    const endpoint = 'https://yourApiUrl.com'; 
    return this.http
        .post(endpoint, newPost, { headers: this.getUploadHeaders() })
        .catch((e) => this.handleError(e));
}

现在你应该在你的组件中创建上传函数,例如 upload.component.ts.下面是一个使用 FormData 上传功能的例子.

And now you should create upload function in your component, for example upload.component.ts. Here is an example for upload function with FormData.

fileToUpload: File = null;

constructor(private uploadService: UploadService) { }

handleFileInput(files: FileList) {
  this.fileToUpload = files.item(0);
}


saveFileToApi() {
  const saveForm: FormData = new FormData();      
  if (this.fileToUpload) {
    // if you need/want to append other fields to API endpoint
    saveForm.append('name', this.name);
    saveForm.append('link', this.link);
    saveForm.append('description', this.description);
    // if you have to append number
    saveForm.append('age', this.age.toString());
    // append image
    saveForm.append('fileFieldNameOnYourApi', this.fileToUpload, this.fileToUpload.name);
  }

  this.uploadService.addNewPost(saveForm).subscribe(() => {
    console.log('Upload success!');
  }, error => {
    console.log('Upload failed!');
  });
}

saveFileToApi 函数中,您还可以附加表单的其他字段.请注意,您应该将数字字段转换为字符串.这里如果使用 FormData 对象,可以阅读更多关于用法的信息.

In saveFileToApi-function you can also append other fields of your form. Beware that you should convert number fields to string. Here you can read more about usage if FormData Objects.

要通过 FormData 上传文件,您需要 3 个参数:API 端点上的 propertyName、文件和此文件的名称.在你的 upload.component.html 中,你需要有这样的形式:

For uploading an file via FormData you need 3 parameters: propertyName on API endpoint, file and name of this file. And in your upload.component.html you need to have form like this one:

<form (ngSubmit)="onSubmit()">     
    <label for="fileField">Chose file to upload</label>
    <input type="file"
           id="fileField"
           name="fileField"
           (change)="handleFileInput($event.target.files)">
    <button type="submit">Speichern</button>
</form>

有关 FormData 的更多详细信息,请阅读 this 以及有关 FormData.append() 的更多信息,请阅读 这个.

For more detail of FormData read this and for more information about FormData.append() read this.

第 2 部分:从 API 获取上传的图片

您应该在 GET-Request 设置中设置 responseType: ResponseContentType.Blob,因为这样您就可以将图像作为 blob 获取并稍后将其转换为 base64 编码源.你上面的代码不好.如果您想正确执行此操作,请创建单独的服务以从 API 获取图像.因为在组件中调用 HTTP-Request 不太好.

You should set responseType: ResponseContentType.Blob in your GET-Request settings, because so you can get your image as blob and convert it later da base64-encoded source. You code above is not good. If you would like to do this correctly, then create separate service to get images from API. Beacuse it ism't good to call HTTP-Request in components.

这是一个工作示例:

创建 image.service.ts 或使用第 1 部分中的 upload.service.ts(也许您可以为该服务命名)并输入以下代码:

Create image.service.ts or use upload.service.ts from part 1 (maybe you can give that service another name) and put following code:

    getImage(imageUrl: string): Observable<File> {
        return this.http
            .get(imageUrl, { responseType: ResponseContentType.Blob })
            .map((res: Response) => res.blob());
    }

现在您需要在 image.component.ts 中创建一些函数来获取图像并将其显示在 html 中.

Now you need to create some function in your image.component.ts to get image and show it in html.

要从 Blob 创建图像,您需要使用 JavaScript 的 FileReader.这是创建新的 FileReader 并监听 FileReader 的加载事件的函数.因此,此函数返回 base64 编码的图像,您可以在 img src-attribute 中使用该图像:

For creating an image from Blob you need to use JavaScript's FileReader. Here is function which creates new FileReader and listen to FileReader's load-Event. As result this function returns base64-encoded image, which you can use in img src-attribute:

imageToShow: any;

createImageFromBlob(image: Blob) {
       let reader = new FileReader();
       reader.addEventListener("load", () => {
          this.imageToShow = reader.result;
       }, false);

       if (image) {
          reader.readAsDataURL(image);
       }
}

现在您应该使用您创建的 ImageService 从 api 获取图像.您应该订阅数据并将此数据提供给 createImageFromBlob-function.这是一个示例函数:

Now you should use your created ImageService to get image from api. You should to subscribe to data and give this data to createImageFromBlob-function. Here is an example function:

getImageFromService() {
      this.isImageLoading = true;
      this.imageService.getImage(yourImageUrl).subscribe(data => {
        this.createImageFromBlob(data);
        this.isImageLoading = false;
      }, error => {
        this.isImageLoading = false;
        console.log(error);
      });
}

现在您可以像这样在 HTML 模板中使用 imageToShow 变量:

Now you can use your imageToShow-variable in HTML template like this:

<img [src]="imageToShow"
     alt="Place image title"
     *ngIf="!isImageLoading; else noImageFound">
<ng-template #noImageFound>
     <img src="fallbackImage.png" alt="Fallbackimage">
</ng-template>

我希望这个描述清晰易懂,你可以在你的项目中使用它.

I hope this description is clear to understand and you can use it in your project.

这篇关于如何将带有表单组值的图像/文件上传到 API?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆