简体   繁体   English

使用redux-form上传图像

[英]Uploading an image with redux-form

I have a react.js redux-form that works and posts data back to my API but I need to also allow the submitter to upload an image with the form, ideally with a preview. 我有一个react.js redux-form,可以工作并将数据发布回我的API,但我还需要让提交者上传带有表单的图像,理想情况下是预览。 I struggled a bit and have arrived at dropzone.js but I can't seem to get my form to actually POST the image data back. 我有点挣扎,已经到达了dropzone.js,但我似乎无法让我的表单实际发回图像数据。

render () {
  const FILE_FIELD_NAME = 'files';

    const renderDropzoneInput = (field) => {
      const files = field.input.value;
      return (
        <div>
          <Dropzone
            name={field.name}
            onDrop={( filesToUpload, e ) => field.input.onChange(filesToUpload)}
          >
            <div>Try dropping some files here, or click to select files to upload.</div>
          </Dropzone>
          {field.meta.touched &&
            field.meta.error &&
            <span className="error">{field.meta.error}</span>}
          {files && Array.isArray(files) && (
            <ul>
              { files.map((file, i) => <li key={i}>{file.name}<img src={file.preview}/></li>) }
            </ul>
          )}
        </div>
      );
    }

    return (
        <form onSubmit={this.props.handleSubmit(this.onSubmit)}>
          <div className="form-group">
            <Field name="files" component={renderDropzoneInput} />
          </div>
          <button type="submit" className="btn btn-default">Submit</button>
        </form>
    );
}

The files variable does get POSTed back to the API which is great but it contains the following: files变量确实被POST回到API,这很好,但它包含以下内容:

[preview=blob:http://localhost:3000/bed3762e-a4de-4d19-8039-97cebaaca5c1]

Can anyone suggest how I get the actual binary data in to that variable please? 任何人都可以建议我如何获得该变量的实际二进制数据?

The full code is available here https://github.com/rushughes/dsloracle/blob/master/client/src/components/LandCreate/index.js 完整代码可在此处获得https://github.com/rushughes/dsloracle/blob/master/client/src/components/LandCreate/index.js

I recently had a similar issue and solved it by using the FileReader API to convert the blob url to Base64 (can also convert to binary string). 我最近遇到了类似的问题并通过使用FileReader API将blob url转换为Base64(也可以转换为二进制字符串)来解决它。

Then you send the Base64 or binary string to the server. 然后将Base64或二进制字符串发送到服务器。

My example code: 我的示例代码:

onDrop(acceptedFiles: any): any {

    let images: any = this.state.Images;

    acceptedFiles.forEach((file: any) => {

        const reader: FileReader = new FileReader();
        reader.onload = () => {
            const fileAsBase64: any = reader.result.substr(reader.result.indexOf(",") + 1);
            images.push(fileAsBase64);
        };

        reader.onabort = () => console.log("file reading was aborted");
        reader.onerror = () => console.log("file reading has failed");

        reader.readAsDataURL(file);
    });

    this.setState(prevState => ({   
         Images: images,
    }));
}

If you want to send a binary string instead of base64 change reader.readAsDataURL(file); 如果要发送二进制字符串而不是base64更改reader.readAsDataURL(file); to reader.readAsBinaryString(file); to reader.readAsBinaryString(file);

and this line: const fileAsBase64: any = reader.result.substr(reader.result.indexOf(",") + 1); 这一行: const fileAsBase64: any = reader.result.substr(reader.result.indexOf(",") + 1); can be simplified to const file: any = reader.result; 可以简化为const file: any = reader.result;

Here are the steps for file-upload feature: (How to handle image data in your API) 以下是file-upload功能的步骤:(如何处理API中的图像数据)

  • Append your redux-form values to the FormData instance. 将redux-form值附加到FormData实例。

     let formData = new FormData(); formData.append('myFile', files[0]); 
  • Send multipart/form-data request from Client to your API with axios or fetch library: 使用axiosfetch库从客户端向您的API发送multipart/form-data请求:

  • Receive that multipart/form-data request in your API, process it with multer and then write the file to the disk storage or memory storage as follows: 在API中接收该multipart/form-data请求,使用multer处理它,然后将文件写入disk storagememory storage ,如下所示:

     $ npm install --save multer 
     const multer = require('multer') const storage = multer.diskStorage({ destination: function (req, file, cb) { cb(null, '/tmp/my-uploads') }, filename: function (req, file, cb) { cb(null, file.fieldname + '-' + Date.now()) } }) const upload = multer({ storage: storage }) const app = express() app.post('/upload', upload.single('myFile'), (req, res, next) => { // req.file is the `myFile` file // req.body will hold the text fields, if there were any }) 
  • (Optional) Serve files directly from your API with Express Serve-Static (可选)使用Express Serve-Static直接从API提供文件

Handle image upload with Node server 使用节点服务器处理图像上载

Try catching file in server endpoint function by using formidable 尝试使用formidable捕获服务器端点函数中的文件

app.post('/upload', function (req, res) { // express endpoint 
    var form = new formidable.IncomingForm();

    form.parse(req, function(err, fields, files) { // "req" is server request object
       fs.rename(files.file.path, "/tmp/" + files.file.name); // move file to desired location
    });

    // handle rest of text fields from req.body if there are any
});

This is node express example, but you can use node http as in formidable example 这是node express示例,但您可以使用节点http作为强大的示例

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM