angulr1.7通过formdata上传图片(显示进度)到springboot

跟着官方httpClient的官方教程做上传文件的component,但是教程的服务端用的是mock的服务,没有带参数,我想上传到springboot,参数名是file,结果试了好久都不行,查了stackoverflow才知道httpclient也要通过formdata上传文件。

原文地址:https://stackoverflow.com/questions/53569024/angular-httpclient-post-two-files-multipart-form-data

文件上传服务
其实基本上是官方的教程,参见:https://angular.io/guide/http#listening-to-progress-events

import { Injectable } from '@angular/core';
import { HttpClient, HttpRequest,HttpHeaders ,HttpEvent, HttpEventType,HttpErrorResponse} from '@angular/common/http';
import { map, tap, last, catchError} from  'rxjs/operators';
import {of} from 'rxjs';

@Injectable(
  {
    providedIn:'root'
  }
)
export class MessageService {
  messages: string[] = [];

  add(message: string) {
    this.messages.push(message);
  }

  clear() {
    this.messages = [];
  }
}

@Injectable({
  providedIn: 'root'
})
export class FileUploadService {

  constructor(private client:HttpClient,private message:MessageService) {

   }
            
   upload(file:File){
           //创建formdata,并把数据添加到formdataz中
           let formData = new FormData();
           formData.append("file",file);
           //创建原始的HttpRequest对象
           //设置reportProgress为true以监听文件上传事件
      let req :HttpRequest<any> =
      new HttpRequest('POST', 'http://localhost:8080/upload',formData, {
      //不用设置请求头,angular会自动设置的
       // headers:new HttpHeaders({'Content-Type':'multipart/form-data'),
        reportProgress: true
      });
     
         

     return   this.client.request(req).pipe(
       //把进度信息添加到消息服务中
         tap(event=>this.getMessage(event)),
         //只返回最后一条消息给调用方
         last(),
         //处理错误
         catchError(this.handleError(file))
     )
   }
   getMessage(event:HttpEvent<any>){
          //跟进度相关的事件有三种
            //sent 代表开始上传

            //UploadProgress代表上传中
            //可以通过event.loaded获得上传了多少
            //通过event.total获得要上传的总数

            //DownloadProgress代表已上传完毕
        if( event.type==HttpEventType.Sent){
             this.message.add("file has been sent");
        }
        if(event.type == HttpEventType.UploadProgress){
           this.message.add(`file has been loaded ${(event.loaded/event.total).toFixed(2)}`)
        }
        if(event.type == HttpEventType.DownloadProgress){
          this.message.add("file has been uploaded")
        }
   }
   private handleError(file: File) {
    const userMessage = `${file.name} upload failed.`;

    return (error: HttpErrorResponse) => {
      // TODO: send the error to remote logging infrastructure
      console.error(error); // log to console instead

      const message = (error.error instanceof Error) ?
        error.error.message :
       `server returned code ${error.status} with body "${error.error}"`;

      this.message.add(`${userMessage} ${message}`);

      // Let app keep running but indicate failure.
      return of(userMessage);
    };
  }
}

组件

import { Component, OnInit } from '@angular/core';
import {FileUploadService,MessageService} from './file-upload.service';
@Component({
  selector: 'app-file-upload',
  templateUrl: './file-upload.component.html',
  styleUrls: ['./file-upload.component.css']
})
export class FileUploadComponent implements OnInit {
   messages:string[];
  constructor(private fileUpload:FileUploadService,private message:MessageService) {
    this.messages = message.messages;
   }

  ngOnInit() {
  }
   pick(ele:HTMLInputElement){
       let file:File =   ele.files[0];
       this.fileUpload.upload(file).subscribe(e=>alert(e));
   }
}

template

<input type="file" #upload />
<input type="button" value="upload" (click)="pick(upload)">

<ul>
  <li *ngFor="let message of messages">{{message}}</li>
</ul>

后台比较简单:

@PostMapping("/upload")
	public Map<String,String> upload(@RequestParam("file") Part file) {
	
		return new HashMap<String,String>(){{
			put("file",file.getSubmittedFileName());
		}};
	}

但是由于上传的文件比较大,需要加上application.properties中的配置


spring.servlet.multipart.max-file-size=300MB
spring.servlet.multipart.enabled=true
spring.servlet.multipart.maxRequestSize=330MB

最后由于angular的服务器和springboot的服务器不在同一个端口上运行,需要解决跨域问题,为此写一个filter

@Component
//标记问filter的注解
@WebFilter
public class CorsFilter implements Filter {

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		// TODO Auto-generated method stub

	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
       HttpServletRequest request1 = (HttpServletRequest)request;
      HttpServletResponse response1 = (HttpServletResponse) response;
      response1.setHeader("Access-Control-Allow-Origin", "*");
     response1.setHeader("Access-Control-Allow-Methods",
          "POST, GET, OPTIONS, DELETE,PUT");
      response1.setHeader("Access-Control-Max-Age", "3600");
      response1.setHeader("Access-Control-Allow-Headers","*");
        // "Content-Type, x-requested-with, X-Custom-Header, Authorization");
		
      chain.doFilter(request, response);
	}

	@Override
	public void destroy() {
		// TODO Auto-generated method stub

	}

}

最后附上network
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值