带有Vue.js / Spring启动的CKEditor5自定义上传适配器

问题描述

我遵循了自定义上传适配器的官方指南,下面是代码

upload-adapter.js

  constructor (loader) {
    this.loader = loader
  }

  upload () {
    return this.loader.file
      .then(file => new Promise((resolve,reject) => {
        this._initRequest()
        this._initListeners(resolve,reject,file)
        this._sendRequest(file)
      }))
  }

  // Aborts the upload process.
  abort () {
    if (this.xhr) {
      this.xhr.abort()
    }
  }

  // Initializes the XMLHttpRequest object using the URL passed to the constructor.
  _initRequest () {
    const xhr = this.xhr = new XMLHttpRequest()
    xhr.open('POST','http://localhost:8090/api/upload',true)
    xhr.responseType = 'json'
  }

  // Initializes XMLHttpRequest listeners.
  _initListeners (resolve,file) {
    const xhr = this.xhr
    const loader = this.loader
    const genericErrorText = `.: ${file.name}.`

    xhr.addEventListener('error',() => reject(genericErrorText))
    xhr.addEventListener('abort',() => reject())
    xhr.addEventListener('load',() => {
      const response = xhr.response

      if (!response || response.error) {
        return reject(response && response.error ? response.error.message : genericErrorText)
      }
      resolve({
        default: response.url
      })
    })
    if (xhr.upload) {
      xhr.upload.addEventListener('progress',evt => {
        if (evt.lengthComputable) {
          loader.uploadTotal = evt.total
          loader.uploaded = evt.loaded
        }
      })
    }
  }

  _sendRequest (file) {
    const data = new FormData()
    data.append('upload',file)
    this.xhr.send(data)
  }
}

因此,后端的端点如下:

xhr.open('POST',true)

然后,http://localhost:8090/api/upload将在下面进行实际上传

ArticleApiController.java

@PostMapping("/api/upload")
    public ResponseEntity<ApiResult> fileUpload(@RequestParam("upload") multipartfile file) {

      try{
          fileService.fileUpload(file);
          return Result.ok("OK");
      }catch (FileStorageException e) {
          String errorMessage = "upload Failed.";
          return Result.failure(errorMessage);
      }
    }

最后一个fileService的描述如下:

fileService.java

@Service
    public class FileService {
        @Value("${app.uploadDir:${user.home}}")
        private String uploadDir;

        public void fileUpload(multipartfile multipartfile) throws Exception {
            Path copyOfLocation = Paths.get(uploadDir + File.separator + StringUtils.cleanPath(multipartfile.getoriginalFilename()));
            try {
                multipartfile.transferTo(copyOfLocation);
            } catch (IOException e) {
                e.printstacktrace();
                throw new FileStorageException("Could not store file : " + multipartfile.getoriginalFilename());
            }

        }
    }

遇到的问题

当我尝试在ckeditor5添加图像时,在upload-adapter.js处看到了500错误。 它报告this.xhr.send(data): Failed to load resource: the server responded with a status of 500 ()

我还看到NullPointerException处的httprequest错误。 完整的响应如下:

{timestamp: "2020-08-26T02:21:35.356+00:00",status: 500,error: "Internal Server Error",…}
error: "Internal Server Error"
message: "No message available"
path: "/api/upload"
status: 500
timestamp: "2020-08-26T02:21:35.356+00:00"
trace: "java.lang.NullPointerException
↵   at bashpound.marketplace.web.apis.ArticleApiController.fileUpload(ArticleApiController.java:109)
↵   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
↵   at sun.reflect.NativeMethodAccessorImpl.invoke(UnkNown Source)
↵   at sun.reflect.DelegatingMethodAccessorImpl.invoke(UnkNown Source)
↵   at java.lang.reflect.Method.invoke(UnkNown Source)
↵   at org.springframework.web.method.support.invocableHandlerMethod.doInvoke(invocableHandlerMethod.java:190)
↵   at org.springframework.web.method.support.invocableHandlerMethod.invokeForRequest(invocableHandlerMethod.java:138)
↵   at org.springframework.web.servlet.mvc.method.annotation.ServletinvocableHandlerMethod.invokeAndHandle(ServletinvocableHandlerMethod.java:105)
↵   at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:878)
↵   at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:792)
↵   at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
↵   at org.springframework.web.servlet.dispatcherServlet.dodispatch(dispatcherServlet.java:1040)
↵   at org.springframework.web.servlet.dispatcherServlet.doService(dispatcherServlet.java:943)
↵   at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
↵   at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
↵   at javax.servlet.http.HttpServlet.service(HttpServlet.java:652)
↵   at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
↵   at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)
↵   at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
↵   at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
↵   at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
↵   at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
↵   at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
↵   at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:200)
↵   at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
↵   at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
↵   at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:320)
↵   at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:126)
↵   at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:90)
↵   at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
↵   at bashpound.marketplace.domain.common.security.ApiRequestAccessDeniedExceptionTranslationFilter.doFilter(ApiRequestAccessDeniedExceptionTranslationFilter.java:27)
↵   at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
↵   at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:118)
↵   at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
↵   at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137)
↵   at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
↵   at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)
↵   at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
↵   at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:158)
↵   at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
↵   at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
↵   at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
↵   at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:200)
↵   at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
↵   at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:200)
↵   at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
↵   at org.springframework.security.web.authentication.logout.logoutFilter.doFilter(logoutFilter.java:116)
↵   at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
↵   at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:92)
↵   at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:77)
↵   at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
↵   at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
↵   at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
↵   at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
↵   at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
↵   at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
↵   at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
↵   at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215)
↵   at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178)
↵   at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358)
↵   at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271)
↵   at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
↵   at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
↵   at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
↵   at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
↵   at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
↵   at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
↵   at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
↵   at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
↵   at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
↵   at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
↵   at org.springframework.boot.actuate.metrics.web.servlet.WebMvcmetricsFilter.doFilterInternal(WebMvcmetricsFilter.java:93)
↵   at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
↵   at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
↵   at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
↵   at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
↵   at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
↵   at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
↵   at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
↵   at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
↵   at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
↵   at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)
↵   at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
↵   at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
↵   at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
↵   at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
↵   at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:373)
↵   at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
↵   at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
↵   at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1589)
↵   at org.apache.tomcat.util.net.socketProcessorBase.run(SocketProcessorBase.java:49)
↵   at java.util.concurrent.ThreadPoolExecutor.runWorker(UnkNown Source)
↵   at java.util.concurrent.ThreadPoolExecutor$Worker.run(UnkNown Source)
↵   at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
↵   at java.lang.Thread.run(UnkNown Source)
↵"

仍然无法理解上载请求为空的原因/原因/位置。 upload-adapter.js似乎没有问题,因为它的编写与指南几乎相同 我怀疑它可能在Vue上,但不幸的是仍然没有任何线索。

WriteArticle.vue

<template>
<ckeditor :editor="editor" v-model="form.content" :config="editorConfig" id="editor"></ckeditor>
</template>


<script>
import ClassicEditor from '@ckeditor/ckeditor5-build-classic'
import Vue from 'vue'
import CKEditor from '@ckeditor/ckeditor5-vue'
import UploadAdapter from '@/utils/upload-adapter'

Vue.use(CKEditor)

export default {
  name: 'WriteArticle',data () {
      ...args
      },editor: ClassicEditor,editorConfig: {
        extraPlugins: [this.MyCustomUploadAdapterPlugin]
      },warn: false
    }
  },components: {
    ckeditor: CKEditor.component
  },methods: {
    ...args
    },MyCustomUploadAdapterPlugin (editor) {
      editor.plugins.get('FileRepository').createUploadAdapter = (loader) => {
        return new UploadAdapter(loader)
      }
    }
  }
}
</script>

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)