angular与springboot实现文件的上传以及照片回显

angular与springboot实现文件的上传以及照片回显

近期进入公司,开始接触angular,并要求使用angular+springboot做一个小例子,其中涉及到了照片上传这方面的知识,做出来以后记录一下踩过的坑,希望之后再做这类功能的时候不要再犯。

文件上传

从前端开始说起,我先把代码贴上,这是文件上传组件的html界面,angular的构造我就不写了,自己看一下官方文档应该就都能明白。

可以看到ngmodel双向绑定的属性是from?.name,那么这里为什么要加这个?呢

?.是angular模板中的安全属性操作符语法,属于angular模板特有语法
a?.b表示当a存在时(不为null或undefined),取a.b的值,否则置空;以避免出现a未赋值时直接报错 详见官方文档
The safe navigation operator ( ?. ) and null property paths

add.component.html
<div class="container" style="width: 30%;margin-left: 35%">
        <h3 class="text-center">新增页面</h3>
        <br/>
        <form  method="post" (ngSubmit)="onSubmit(regForm.value)" #regForm="ngForm">
                <div class="form-group" >
                    <label for="name">姓名</label>
                    <input type="text" class="form-control" name="name" (ngModel)="from?.name" placeholder="请输入姓名">
                </div>
                <div class="form-group" >
                     <label for="name">性别</label><br/>
                    <input type="radio" class="" name="sex"  (ngModel)="from?.sex" value=""/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
                    <input type="radio" class="" name="sex"  (ngModel)="from?.sex" value=""/></div>
                <div class="form-group" >
                    <label for="name">出生日期</label>
                    <input class="form-control" type="text" id="date" name="date"  autocomplete="off" (ngModel)="from?.date" placeholder="请选择出生日期"/>
                </div>
                <div class="form-group" >
                    <label for="name">手机号</label>
                    <input class="form-control" type="text" name="phonenum" (ngModel)="from?.phonenum" placeholder="请输入手机号"/>
                </div>
                <div class="form-group" >
                    <label for="name">地址</label>
                    <input class="form-control" type="text" name="local" (ngModel)="from?.local" placeholder="请输入地址"/>
                </div>
                <div class="form-group">
                    <label for="inputfile">照片</label><br/>
                    <img height="100px" width="200px" [src]="_d.bypassSecurityTrustUrl(imgsrc)"/><br/>
                    <br/>
                    <input type="file" name="photo" id="photo" (change)="fileChange($event)"  (ngModel)="from?.photo" />
                </div>
                <div class="form-group">
                        <button type="submit" class="btn btn-primary btn-block btn-sm" style="width:100px">提交</button>
                </div>
        </form>
    </div>

这里我是通过angular的form表单提交的文件,以及除了文件之外的一些参数,比如手机号、姓名还有性别啥的,我把代码改的尽量简单,看一下ts文件中是怎么接收的。

add.comentpont.ts
import { Component, OnInit } from '@angular/core';
import { ListService } from '../list.service'
import { DomSanitizer } from '@angular/platform-browser';
import { Router } from '@angular/router';
import { Location } from '@angular/common';

declare let laydate;

@Component({
  selector: 'app-add',
  templateUrl: './add.component.html',
  styleUrls: ['./add.component.css']
})
export class AddComponent implements OnInit {
  /**声明表单变量 */
  from:{
    name:String,
    sex:String,
    date:String,
    phonenum:String,
    local:String,
    photo:File
  }
  /**设置的图片框默认显示一张图片*/
   imgsrc = 'http://localhost:8888/images/20190807152104882.jpg';
   date:string;
   file:any;
   formdate:FormData
  constructor(
    private listservice:ListService,
    private router:Router,
    public _d: DomSanitizer,
    private location: Location
  ) { }

  ngOnInit() {
  /**使用了layui的日期插件*/
    laydate.render({
      elem:'#date',
      theme:'#4DC6FD',
      done:(value,date,endDate)=>{
        this.date=value;
      }
    });
  }
  onSubmit(value):void{
    this.formdate=new FormData();
    this.formdate.append("name",value.name)
    this.formdate.append("sex",value.sex)
    this.formdate.append("date",this.date)
    this.formdate.append("phonenum",value.phonenum)
    this.formdate.append("local",value.local)
    this.formdate.append("file",this.file)
    this.listservice.onSubmit(this.formdate).subscribe(
    //执行成功以后通过路由进行组件跳转
    ()=>this.router.navigate(['admin/addresslist'])
    );
  }
  //上传文件的input框的监听事件
  fileChange(e) {
    this.file = e.srcElement.files[0]; // 获取图片这里只操作一张图片
    this.imgsrc = window.URL.createObjectURL(this.file); // 获取上传的图片临时路径
  }

}

拿到表单的数据之后,把数据全都给append进了一个FormData对象中,一般通过Ajax上传文件的话应该都是通过formdata来传的

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { List } from './List';
import { HttpClient, HttpHeaders }    from '@angular/common/http';
import { catchError, map, tap } from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})
export class ListService {
  file = new FormData();

  constructor(public http:HttpClient) { }
//将我们的参数以及上传的文件提交给服务器
  onSubmit(formdate:any):Observable<{}>{
    let api = 'http://localhost:8888/listController/addtest'
    //我们知道post方法有三个参数,切记,最后一个参数不要写,空着,angular会自动判断应该使用什么请求头,因为包含文件,规定特定的请求头的话可能会出错,所以索性不要规定
    return this.http.post(api,formdate);
  }
}

到这里为止,angular做的工作就完成了

springboot接收数据

ListController.java
@Controller
@CrossOrigin
@RequestMapping("/listController")
public class ListController {
    @Autowired
    private ListService listService;
    
    /**
     * 新建页面添加数据
     * 使用MultipartFile接口接收前台传的file(文件),其他的参数用实体类接收就可以了
     */
    @PostMapping("/addtest")
    @ResponseBody
    public int addtest(@RequestParam("file") MultipartFile file, Formlist formlist) throws IOException{
        if(file.isEmpty()){
            System.out.println("file为空");
        }
        //使用时间给上传的文件命名,这种方式没有用uuid命名好,因为同一时间有可能会上传多个文件
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSS");
        String res = sdf.format(new Date());
        String originaFilename = file.getOriginalFilename();
        //获取文件的后缀名
        String newFileName = res+originaFilename.substring(originaFilename.lastIndexOf("."));
        String rootPath = "/images/";
        File newFile = new File(rootPath+newFileName);
        System.out.println(rootPath+newFileName);
        //定义向数据库中存取的文件路径
        String src=rootPath+newFileName;
        if(!newFile.getParentFile().exists()){
            newFile.getParentFile().mkdirs();
        }else{
            System.out.println(newFile.getParentFile());
        }
        if(!newFile.exists()){
        //使用transferTo()方法将文件存到所在服务器上
            file.transferTo(newFile);
        }
        return listService.add(src,formlist);
    }
}

这里我们还需要配置两个文件

application.java 我们的启动文件中配置文件存放的路径
@SpringBootApplication
@EnableScheduling
@MapperScan("MpTest.dao")
public class Application {
    public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
}
    @Bean
    MultipartConfigElement multipartConfigElement(){
        MultipartConfigFactory factory = new MultipartConfigFactory();
        factory.setLocation("E:/gitprogram/MP/src/main/resources/static");
        return factory.createMultipartConfig();
    }
}
UploadConfiguration.java

重写addResourceHandlers方法,设置照片回显时的虚拟路径,这样我们在前台查看我们的照片或者文件的时候只需要使用http://IP:port/‘数据库中取到的路径’ 就可以访问了

@Configuration
public class UploadConfiguration  extends WebMvcConfigurationSupport {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry){
        registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
        registry.addResourceHandler("/images/**")
                .addResourceLocations("file:E:/gitprogram/MP/src/main/resources/static/images/");
    }
}

后边的代码就是将我们获取的这些数据存在数据库中了,因为我用的mp就不贴出来了,看一下前台获取数据时的代码吧。

 <div class="col-xs-2 col-sm-2 text-center center-vertical"><img *ngIf="item.photo" height="50px" width="100px" src="http://127.0.0.1:8888/{{item.photo}}"></div>
发布了12 篇原创文章 · 获赞 1 · 访问量 1062

猜你喜欢

转载自blog.csdn.net/Genjicoo/article/details/98966308
今日推荐