【问题标题】:Uploading a file to Spring web service using Angular 7使用 Angular 7 将文件上传到 Spring Web 服务
【发布时间】:2019-11-22 05:31:29
【问题描述】:

我正在处理 Angular 项目,同时我想将我的图像文件上传到 Web 服务器。我正在使用 Spring Web 服务来上传这些文件。 我从 Youtube 视频中观看了这段代码。 我使用的 HTML 是:

<div class="container-fluid">
  <h2>Entering a product</h2>
  <h4 *ngIf="submitted" class="text-success text">{{product_NAME.value}} has been submitted successfull.</h4>
  <form [formGroup]="insertProduct" (ngSubmit)="onSubmit()">
    {{insertProduct.value | json}}
    <div class="form-group">
      <label for="product_NAME">Product Name:</label>
      <input required type="text" name="product_NAME" formControlName="product_NAME" class="form-control">
    </div>
    <div class="form-group">
      <label for="product_PRICE">Sale Price:</label>
      <input required type="number" name="product_PRICE" formControlName="product_PRICE" class="form-control">
    </div>    
    <div class="form-group">
      <label for="product_STOCK">Stock:</label>
      <input required type="number" name="product_STOCK" formControlName="product_STOCK" class="form-control">
    </div>
    <div class="form-group">
      <label for="product_DESCRIPTION">Description:</label>
      <textarea required class="form-control" rows="5" formControlName="product_DESCRIPTION"></textarea>
    </div> 
    <div class="form-group">
      <select formControlName="productcategory_ID" class="custom-select" name="productcategory_ID" [class.is-invalid]="(hasError && productcategory_ID.touched)" (change)="validateType(productcategory_ID.value)">
      <option  value="default" selected>Select a Product Type</option>
      <option *ngFor="let type of productTypes" value={{type.productcatergory_ID}}>{{type.productcatergory_NAME}}</option>        
      </select>
      <small class="text-danger" *ngIf="hasError && productcategory_ID.touched">Please choose an appropriete type.</small> 
    </div>
    <div class="form-group">
      <label for="productimage_ID">Select an image:</label>
      <input required type="file" accept=".jpg, .jpeg, .png" formControlName="productimage_ID" class="form-control" (change)="onFileSelected($event)">      
    </div>
    <button class="btn btn-primary" type="submit">Insert product</button>
  </form>
  <!-- for button above [disabled]="insertProduct.invalid" -->
</div>
<!-- For displaying name of file.. -->
<script>
  // Add the following code if you want the name of the file appear on select
  $(".custom-file-input").on("change", function() {
    var fileName = $(this).val().split("\\").pop();
    $(this).siblings(".custom-file-label").addClass("selected").html(fileName);
  });
  </script>

使用文件输入注册的更改事件的打字稿代码是:

onFileSelected(event){
    this.userFile=<File>event.target.File;
    console.log(event);
    console.log(this.userFile);

  }

为了订阅服务,我使用以下代码向其发送表单数据:

onSubmit(){
    const fd:FormData=new FormData();    
    fd.append('file', this.userFile); 
    console.log(this.insertProduct.value);
    console.log(fd);

    this.service.insertImage(fd)
      .subscribe(
        res=>console.log(res),
        error=>console.log(error)        
      )
}

我在 Angular 中使用的服务类是:

import { Injectable } from '@angular/core';
import { Observable, throwError } from 'rxjs';
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { catchError } from 'rxjs/operators';
import { Product } from './Interfaces/product';

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

  // headers = new HttpHeaders({'Access-Control-Allow-Origin' : '*'})
  path: string="http://localhost:8080/productcategory";
  productPath: string="http://localhost:8080/product";
  constructor(private http: HttpClient) { }
//Posting image using form-data
  insertImage(file: FormData){
    var path=this.productPath+"/image";
    return this.http.post(path, File)
                .pipe(catchError(this.errorHandler));
  }

}

现在我要提供我在 java spring 中调用的服务是:

// posting image in local path
    @PostMapping("image")
    public String saveFile(@RequestParam("file") MultipartFile file) throws IOException {
        String directorypath = "E:\\Faltu Setup\\Tutorials\\Angular.JS Learning Path\\Youtube Tutorials\\Pratices(ANGULAR)\\Project\\src\\assets\\Images\\ItemIcons";
        SimpleDateFormat dateFormat = new SimpleDateFormat("ddMMyy-hhmmss");
        ObjectMapper mapper = new ObjectMapper();
        Date date = new Date();
        String fileName = "";
        if (!file.isEmpty()) {
            try {
                String[] split = file.getOriginalFilename().split("\\.");
                String ext = split[split.length - 1];
                fileName = "File-" + dateFormat.format(date) + "." + ext;
                log.info(file.getName());
                log.info(file.getContentType());
                log.info(file.getOriginalFilename());
                log.info(fileName);
                if (Files.notExists(Paths.get(directorypath), LinkOption.NOFOLLOW_LINKS)) {
                    Files.createDirectory(Paths.get(directorypath));
                    log.debug("I am entered.");
                }
                Files.copy(file.getInputStream(), Paths.get(directorypath + "/" + fileName));
            } catch (IOException e) {
                return mapper.writeValueAsString(e.getMessage());
            }catch(RuntimeException e) {
                return mapper.writeValueAsString(e.getMessage());
            }
        }
        return mapper.writeValueAsString(fileName);
    }

一切正常,现在你已经理解了我使用的所有代码,但是当我订阅它显示的服务时:

org.springframework.web.multipart.MultipartException: Current request is not a multipart request
    at org.springframework.web.method.annotation.RequestParamMethodArgumentResolver.handleMissingValue(RequestParamMethodArgumentResolver.java:190) ~[spring-web-4.3.9.RELEASE.jar:4.3.9.RELEASE]
    at org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java:109) ~[spring-web-4.3.9.RELEASE.jar:4.3.9.RELEASE]
    at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121) ~[spring-web-4.3.9.RELEASE.jar:4.3.9.RELEASE]
    at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:158) ~[spring-web-4.3.9.RELEASE.jar:4.3.9.RELEASE]
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:128) ~[spring-web-4.3.9.RELEASE.jar:4.3.9.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97) ~[spring-webmvc-4.3.9.RELEASE.jar:4.3.9.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) ~[spring-webmvc-4.3.9.RELEASE.jar:4.3.9.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) ~[spring-webmvc-4.3.9.RELEASE.jar:4.3.9.RELEASE]
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) ~[spring-webmvc-4.3.9.RELEASE.jar:4.3.9.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967) ~[spring-webmvc-4.3.9.RELEASE.jar:4.3.9.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901) ~[spring-webmvc-4.3.9.RELEASE.jar:4.3.9.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) ~[spring-webmvc-4.3.9.RELEASE.jar:4.3.9.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872) ~[spring-webmvc-4.3.9.RELEASE.jar:4.3.9.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:661) ~[tomcat-embed-core-8.5.15.jar:8.5.15]
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) ~[spring-webmvc-4.3.9.RELEASE.jar:4.3.9.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) ~[tomcat-embed-core-8.5.15.jar:8.5.15]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-8.5.15.jar:8.5.15]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.15.jar:8.5.15]
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) ~[tomcat-embed-websocket-8.5.15.jar:8.5.15]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.15.jar:8.5.15]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.15.jar:8.5.15]
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) ~[spring-web-4.3.9.RELEASE.jar:4.3.9.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.9.RELEASE.jar:4.3.9.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.15.jar:8.5.15]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.15.jar:8.5.15]
    at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:105) ~[spring-web-4.3.9.RELEASE.jar:4.3.9.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.9.RELEASE.jar:4.3.9.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.15.jar:8.5.15]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.15.jar:8.5.15]
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81) ~[spring-web-4.3.9.RELEASE.jar:4.3.9.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.9.RELEASE.jar:4.3.9.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.15.jar:8.5.15]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.15.jar:8.5.15]
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) ~[spring-web-4.3.9.RELEASE.jar:4.3.9.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.9.RELEASE.jar:4.3.9.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.15.jar:8.5.15]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.15.jar:8.5.15]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) ~[tomcat-embed-core-8.5.15.jar:8.5.15]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.15.jar:8.5.15]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478) [tomcat-embed-core-8.5.15.jar:8.5.15]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.15.jar:8.5.15]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80) [tomcat-embed-core-8.5.15.jar:8.5.15]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.15.jar:8.5.15]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [tomcat-embed-core-8.5.15.jar:8.5.15]
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799) [tomcat-embed-core-8.5.15.jar:8.5.15]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.15.jar:8.5.15]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:861) [tomcat-embed-core-8.5.15.jar:8.5.15]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455) [tomcat-embed-core-8.5.15.jar:8.5.15]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.15.jar:8.5.15]
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1135) [na:na]
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) [na:na]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.15.jar:8.5.15]
    at java.base/java.lang.Thread.run(Thread.java:844) [na:na]

虽然它在浏览器的控制台中给出了以下相同的异常:

org.springframework.web.multipart.MultipartException

我尽力了,但无济于事。等待您的回复。 提前致谢。

【问题讨论】:

  • 图片服务在/product下面,所以它调用的是正确的服务,所以你不用担心我在productpath下调用/image服务。
  • 异常消息:Current request is not a multipart request 所以请检查您的表单并添加enctype="multipart/form-data"

标签: angular spring file-upload form-data


【解决方案1】:

在您的服务中:

return this.http.post(path, File)
            .pipe(catchError(this.errorHandler));

可能你应该将文件更改为文件,因为 ts 区分大小写?

【讨论】:

    【解决方案2】:

    Current request is not a multipart request 提示您的请求不是 Spring Boot 期望的多部分请求。为此,

    您必须在表单中添加enctype="multipart/form-data"

    <form [formGroup]="insertProduct" enctype="multipart/form-data (ngSubmit)="onSubmit()">
    

    这里你有文件而不是文件。 change File to file 如下。

    insertImage(file: FormData){
        var path=this.productPath+"/image";
        return this.http.post(path, file)
                    .pipe(catchError(this.errorHandler));
      }
    

    另外,在application.properties 中添加以下内容。您可以根据需要更改值。

    ## MULTIPART (MultipartProperties)
    # Enable multipart uploads
    spring.servlet.multipart.enabled=true
    # Threshold after which files are written to disk.
    spring.servlet.multipart.file-size-threshold=2KB
    # Max file size.
    spring.servlet.multipart.max-file-size=500MB
    # Max Request Size
    spring.servlet.multipart.max-request-size=500MB
    spring.servlet.multipart.location=E:\\Faltu Setup\\Tutorials\\Angular.JS Learning Path\\Youtube Tutorials\\Pratices(ANGULAR)\\Project\\src\\assets\\Images\\ItemIcons
    

    【讨论】:

    • 感谢大家的宝贵时间,但现在按照上述所有步骤,它在浏览器控制台中给了我这样的例外error: "Bad Request" ​​ exception: "org.springframework.web.multipart.support.MissingServletRequestPartException" ​​ message: "Required request part 'file' is not present"
    • 当我在控制台上使用表单打印时,它会给出该控件保存文件的以下值C:\\fakepath\\Capture.PNG
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-11-11
    • 1970-01-01
    • 2012-01-16
    • 1970-01-01
    • 2020-06-05
    • 2017-07-28
    • 1970-01-01
    相关资源
    最近更新 更多