TypeError:无法将未定义或null转换为对象React JS(S3分段文件上传)

时间:2018-11-08 11:11:16

标签: reactjs amazon-s3 multipartform-data

我正在尝试使用S3分段上传方法将图像/视频文件上传到S3存储桶。之后,我找到了 ReactS3Uploader npm软件包。从我的React组件导入此包后,我不断收到 TypeError:从浏览器中选取文件时,无法将未定义或null转换为对象的错误消息。

错误消息:

        Pre-process: 2.png
        Upload progress: 0% Waiting

        Uncaught TypeError: Cannot convert undefined or null to object
        at Function.assign (<anonymous>)
        at S3Upload.push../node_modules/react-s3-uploader-multipart/s3upload.js.S3Upload.uploadToS3 (s3upload.js:64)
        at S3Upload.push../node_modules/react-s3-uploader-multipart/s3upload.js.S3Upload.uploadFile (s3upload.js:95)
        at S3Upload.<anonymous> (s3upload.js:57)
        at S3Upload.preprocess (ReactS3Uploader.js:35)
        at S3Upload.push../node_modules/react-s3-uploader-multipart/s3upload.js.S3Upload.handleFileSelect (s3upload.js:55)
        at new S3Upload (s3upload.js:47)
        at Object.uploadFile (ReactS3Uploader.js:56)
        at HTMLUnknownElement.callCallback (react-dom.development.js:147)
        at Object.invokeGuardedCallbackDev (react-dom.development.js:196)
        at invokeGuardedCallback (react-dom.development.js:250)
        at invokeGuardedCallbackAndCatchFirstError (react-dom.development.js:265)
        at executeDispatch (react-dom.development.js:571)
        at executeDispatchesInOrder (react-dom.development.js:596)
        at executeDispatchesAndRelease (react-dom.development.js:695)
        at executeDispatchesAndReleaseTopLevel (react-dom.development.js:704)
        at forEachAccumulated (react-dom.development.js:676)
        at runEventsInBatch (react-dom.development.js:844)
        at runExtractedEventsInBatch (react-dom.development.js:852)
        at handleTopLevel (react-dom.development.js:5025)
        at batchedUpdates$1 (react-dom.development.js:19904)
        at batchedUpdates (react-dom.development.js:2246)
        at dispatchEvent (react-dom.development.js:5105)
    push../node_modules/react-s3-uploader-multipart/s3upload.js.S3Upload.uploadToS3 @ s3upload.js:64
    push../node_modules/react-s3-uploader-multipart/s3upload.js.S3Upload.uploadFile @ s3upload.js:95
    (anonymous) @ s3upload.js:57
    preprocess @ ReactS3Uploader.js:35
    push../node_modules/react-s3-uploader-multipart/s3upload.js.S3Upload.handleFileSelect @ s3upload.js:55
    S3Upload @ s3upload.js:47
    uploadFile @ ReactS3Uploader.js:56
    callCallback @ react-dom.development.js:147
    invokeGuardedCallbackDev @ react-dom.development.js:196
    invokeGuardedCallback @ react-dom.development.js:250
    invokeGuardedCallbackAndCatchFirstError @ react-dom.development.js:265
    executeDispatch @ react-dom.development.js:571
    executeDispatchesInOrder @ react-dom.development.js:596
    executeDispatchesAndRelease @ react-dom.development.js:695
    executeDispatchesAndReleaseTopLevel @ react-dom.development.js:704
    forEachAccumulated @ react-dom.development.js:676
    runEventsInBatch @ react-dom.development.js:844
    runExtractedEventsInBatch @ react-dom.development.js:852
    handleTopLevel @ react-dom.development.js:5025
    batchedUpdates$1 @ react-dom.development.js:19904
    batchedUpdates @ react-dom.development.js:2246
    dispatchEvent @ react-dom.development.js:5105

这是我的代码示例,

import React, { Component } from 'react';
import './App.css';
var ReactS3Uploader = require('react-s3-uploader-multipart');
class App extends Component {
   render() {
    return (
      <div className="App">
        <ReactS3Uploader
          signingUrl="/s3/sign"
          signingUrlMethod="GET"
          accept="image/*"
          s3path="/uploads/"
          preprocess={this.onUploadStart}
          onProgress={this.onUploadProgress}
          onError={this.onUploadError}
          onFinish={this.onUploadFinish}
          signingUrlWithCredentials={true}
          uploadRequestHeaders={{ 'x-amz-acl': 'public-read' }}  
          contentDisposition="auto"
          scrubFilename={(filename) => 
             filename.replace(/[^\w\d_\-.]+/ig, '')}
          server="http://cross-origin-server.com"
          inputRef={cmp => this.uploadInput = cmp}
          autoUpload={true}
       />
    </div>
  );
}
}

export default App;

Package.json:

   {
    "name": "s3",
    "version": "0.1.0",
    "private": true,
    "dependencies": {
      "react": "^16.6.1",
      "react-dom": "^16.6.1",
      "react-s3-uploader-multipart": "^4.8.0",
      "react-scripts": "2.1.1"
    },
    "scripts": {
      "start": "react-scripts start",
      "build": "react-scripts build",
      "test": "react-scripts test",
      "eject": "react-scripts eject"
    },
    "eslintConfig": {
      "extends": "react-app"
    },
    "browserslist": [
      ">0.2%",
      "not dead",
      "not ie <= 11",
      "not op_mini all"
    ]
  }

谢谢。

1 个答案:

答案 0 :(得分:1)

react-s3-uploader-multipart模块必须先对其源代码进行一些修改才能使用。

您看到,记录到控制台的错误是由于Line 63 of s3Upload.js上对象分配的结果

var evaporateOptions = Object.assign(this.evaporateOptions, {
    signerUrl: this.signingUrl
});

发生这种情况的原因是,当在line 65 of ReactS3Upload.js中调用S3Upload时,它不会转发创建evaporateOptions React Element时必须设置的ReactS3Uploader属性。

    this.myUploader = new S3Upload({
        fileElement: ReactDOM.findDOMNode(this),
        signingUrl: this.props.signingUrl,
        getSignedUrl: this.props.getSignedUrl,
        preprocess: this.props.preprocess,
        onProgress: this.props.onProgress,
        onFinishS3Put: this.props.onFinish,
        onError: this.props.onError,
        signingUrlMethod: this.props.signingUrlMethod,
        signingUrlHeaders: this.props.signingUrlHeaders,
        signingUrlQueryParams: this.props.signingUrlQueryParams,
        signingUrlWithCredentials: this.props.signingUrlWithCredentials,
        uploadRequestHeaders: this.props.uploadRequestHeaders,
        contentDisposition: this.props.contentDisposition,
        server: this.props.server,
        scrubFilename: this.props.scrubFilename,
        s3path: this.props.s3path,
        evaporateOptions: this.props.evaporateOptions // this is missing
    });

s3upload.js的{​​{3}}和Line 68中,this.s3Pathundefined,而这些行中的属性访问应为this.s3path < / p>

这使您可以选择创建存储库的分支,进行此更改并提出将其合并到上游并部署到npm注册表的请求 或在npm软件包注册表中查找另一个。

如果进行此更改,则必须Line 103作为道具传递。 例如

import crypto from 'crypto';

const config = {
  signerUrl: 'auth_upload',
  aws_key: 'AKALN0L7ASDFLKJH',
  bucket: 'my-big-bucket',
  computeContentMd5: true,
  cryptoHexEncodedHash256: data => crypto.createHash('sha256').update(data).digest('hex'),
  cryptoMd5Method: data => crypto.createHash('md5').update(data).digest('base64')
};

<ReactS3Uploader
  accept="image/*"
  s3path="uploads/"
  signingUrlWithCredentials={true}
  uploadRequestHeaders={{ 'x-amz-acl': 'public-read' }}  
  contentDisposition="auto"
  server="<backend-svc>"
  inputRef={ref => (this.uploadInput = ref)}
  evaporateOptions={config}
/>

此外,还需要在支持服务中实现端点以对S3上传URL进行签名。 请参见此evaporateOptions,以获取有关其实现方式的示例。