使用react + Vertx上传文件

时间:2018-06-07 05:10:07

标签: reactjs file-upload react-redux vert.x

我正在开发一个Web应用程序,我必须上传一个用Java + VertX编写的服务器文件

端点是这样的:

private void uploadFromExcel(RoutingContext ctx) {    
    new ImportFromExcel(ctx.getBody(), ctx.vertx()).startImporting(ev->{
        if(ev.failed()){
            ctx.fail(ev.cause());
        }else {
            ctx.response().end();
        }
    });        
}

这样的前端是这样的:

<input
   accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel"
   type="file"
   onChange={this.onUploadFile}
 />
   <label htmlFor="flat-button-file">
     <IconButton component="span">
         <Icon className={'material icons'}>cloud_upload</Icon>
     </IconButton>
   </label>

[...]

onUploadFile = (e) =>{
   const {reduxApi, setError, setWait, removeWait} = this.context
   const { dispatchUploadFile } = this.props

   const fileToUpload = e.target.files[0]

   dispatchUploadFile(reduxApi, fileToUpload , (err,data)=>{
      removeWait()
      //e.target.value = null
      if(err){
        setError(err)
        return
       }
   })

   [...]

   dispatchUploadFile: (reduxApi, file, cb) =>{
      dispatch(reduxApi.actions.cryptoindexUploadExcel.post(null,file,cb))
   }

我可以使用Header&#34; Accept-Type&#34;:&#34; multipart / form-data&#34;通过邮递员上传文件。它工作正常!

不幸的是我无法通过反应上传文件,它会抛出错误。所以我决定尝试另一种解决方案

let  reader = new FileReader()
reader.onload = (event)  => {
    let arrayBuffer = event.target.result
    let array = new Uint8Array(arrayBuffer)
    let binaryString = String.fromCharCode.apply(null, array)
    console.log(binaryString)

    setWait()
    dispatchUploadFile(reduxApi, array , (err,data)=>{
      removeWait()
      if(err){
        setError(err)
        return
      }
    })

}
reader.readAsArrayBuffer(fileToUpload)

这段代码读取文件,但后端部分显示&#34;零字节长文件&#34;。你有什么解决办法?谢谢!

2 个答案:

答案 0 :(得分:1)

我假设在服务器端你的路由器中有BodyHandler

router.route().handler(BodyHandler.create());

现在,根据您上传文件的方式,它可能会在两个地方结束:

如果是multipart/form-data,它将在fileUploads() getter下的上下文中可用:

Set<FileUpload> uploads = routingContext.fileUploads();
// Do something with uploads....

它是一个正文上传,例如AJAX调用application/json,它最终会出现在body() getter中。因此,请确保您使用正确的标题,因为在上传过程中浏览器和服务器对它们的处理方式不同。

答案 1 :(得分:0)

解决了!问题出在前端。我用这种方式使用XMLTHTTPRequest重写了上传方法:

onUploadFile = (e) =>{
    if(!e.target.files || e.target.files.length==0) return

    const {reduxApi, setError, setWait, removeWait} = this.context
    const fileToUpload = e.target.files[0]

    setWait()

    const xhr = new XMLHttpRequest()
    xhr.open('POST', getRootURL() + "/cryptoindex/index/excel")

   xhr.onload = () => {
     removeWait()
     if(xhr.status!=200){
        setError({...xhr, responseJSON: JSON.parse(xhr.responseText)})
     }else{
       this.refreshAll()
     }
   }

    xhr.send(fileToUpload)
 }

这不是最好的解决方案,但它有效!