Wie aktiviere ich das Hochladen von Dateien auf der einfachen Material-Benutzeroberfläche von React?

73

Ich erstelle ein einfaches Formular zum Hochladen einer Datei mit einem Elektronenreaktions-Boilerplate mit Redux-Formular und Material-Benutzeroberfläche.

Das Problem ist, dass ich nicht weiß, wie man ein Eingabedateifeld erstellt, da die Material-Benutzeroberfläche die Eingabe von Upload-Dateien nicht unterstützt.

Irgendwelche Ideen, wie dies erreicht werden kann?

gintoki27
quelle
Dieser Link enthält einen Code zur Vorgehensweise kiranvj.com/blog/blog/file-upload-in-material-ui mit einem funktionierenden Codesandbox-Link
kiranvj

Antworten:

90

Die API bietet componentzu diesem Zweck.

<Button
  variant="contained"
  component="label"
>
  Upload File
  <input
    type="file"
    hidden
  />
</Button>
Elijahcarrel
quelle
3
anstatt zu verwenden style={{ display: "none" }}, können Sie einfach setzenhidden
Will59
88

neuere MUI-Version:

<input
  accept="image/*"
  className={classes.input}
  style={{ display: 'none' }}
  id="raised-button-file"
  multiple
  type="file"
/>
<label htmlFor="raised-button-file">
  <Button variant="raised" component="span" className={classes.button}>
    Upload
  </Button>
</label> 
galki
quelle
4
Vielen Dank, dies ist ein Beispiel hier . Sie müssen auch Stil input: {display: 'none'} für dieses Element hinzufügen .
Alex Zamai
5
Oder einfach<input hidden>
Olefrank
4
Hallo - Sobald eine Datei hochgeladen wurde (dh wenn Sie eine Datei markieren und auf das eingeblendete Formular klicken), wird ein onChangeEreignis auf dem <input />aufgerufen, aber meine Datei ist nicht in der targetEigenschaft des Ereignisobjekts (oder einer Eigenschaft auf) verfügbar das Ereignisobjekt, das ich sehen kann). Wo ist die Datei verfügbar?
jboxxx
2
@jboxxx: Die Datei (en) sind eingeschaltet target.files( inputElemente haben ein eingebautes filesAttribut, das jede ausgewählte Datei
auflistet
2
In der neuesten Version variant="raised"ist veraltet, es erwartet einen von ["Text", "umrissen", "enthalten"]
Renan Borges
34

Sie müssen Ihre Eingabe mit einschließen Komponente, und fügen Sie die containerElement- Eigenschaft mit dem Wert 'label' hinzu ...

<RaisedButton
   containerElement='label' // <-- Just add me!
   label='My Label'>
   <input type="file" />
</RaisedButton>

Weitere Informationen finden Sie in dieser GitHub- Ausgabe .

BEARBEITEN: Update 2019.

Überprüfen Sie unten die Antwort von @galki

TLDR;

<input
  accept="image/*"
  className={classes.input}
  style={{ display: 'none' }}
  id="raised-button-file"
  multiple
  type="file"
/>
<label htmlFor="raised-button-file">
  <Button variant="raised" component="span" className={classes.button}>
    Upload
  </Button>
</label> 
Vedran
quelle
2
Wie verwende ich dieses Dateiobjekt? HTML FileReader scheint nicht zu funktionieren: / In Anbetracht dessen habe ich<input type='file' onChange='handleFile'> handleFile = file => { .. }
Paulo
2
Schauen Sie sich die Antwort von @ galki unten an, wenn Sie diese im Jahr 2019 besuchen: D
Blundering Philosopher
23

Hier ist ein Beispiel für die Verwendung eines IconButton zum Erfassen von Eingaben (Foto- / Videoaufnahme) mit Version 3.9.2:

import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';

import { withStyles } from '@material-ui/core/styles';
import IconButton from '@material-ui/core/IconButton';
import PhotoCamera from '@material-ui/icons/PhotoCamera';
import Videocam from '@material-ui/icons/Videocam';

const styles = (theme) => ({
    input: {
        display: 'none'
    }
});

class MediaCapture extends Component {
    static propTypes = {
        classes: PropTypes.object.isRequired
    };

    state: {
        images: [],
        videos: []
    };

    handleCapture = ({ target }) => {
        const fileReader = new FileReader();
        const name = target.accept.includes('image') ? 'images' : 'videos';

        fileReader.readAsDataURL(target.files[0]);
        fileReader.onload = (e) => {
            this.setState((prevState) => ({
                [name]: [...prevState[name], e.target.result]
            }));
        };
    };

    render() {
        const { classes } = this.props;

        return (
            <Fragment>
                <input
                    accept="image/*"
                    className={classes.input}
                    id="icon-button-photo"
                    onChange={this.handleCapture}
                    type="file"
                />
                <label htmlFor="icon-button-photo">
                    <IconButton color="primary" component="span">
                        <PhotoCamera />
                    </IconButton>
                </label>

                <input
                    accept="video/*"
                    capture="camcorder"
                    className={classes.input}
                    id="icon-button-video"
                    onChange={this.handleCapture}
                    type="file"
                />
                <label htmlFor="icon-button-video">
                    <IconButton color="primary" component="span">
                        <Videocam />
                    </IconButton>
                </label>
            </Fragment>
        );
    }
}

export default withStyles(styles, { withTheme: true })(MediaCapture);
Markus Hay
quelle
Die Komponente = "span" wird definitiv für IconButton benötigt, das hat mir gefehlt!
Locutus
12

Es ist Arbeit für mich ("@ material-ui / core": "^ 4.3.1"):

    <Fragment>
        <input
          color="primary"
          accept="image/*"
          type="file"
          onChange={onChange}
          id="icon-button-file"
          style={{ display: 'none', }}
        />
        <label htmlFor="icon-button-file">
          <Button
            variant="contained"
            component="span"
            className={classes.button}
            size="large"
            color="primary"
          >
            <ImageIcon className={classes.extendedIcon} />
          </Button>
        </label>
      </Fragment>
Alexei Zababurin
quelle
1

Genauso wie es sein sollte, aber ändern Sie die Schaltflächenkomponente so, dass sie so beschriftet ist

<form id='uploadForm'
      action='http://localhost:8000/upload'
      method='post'
      encType="multipart/form-data">
    <input type="file" id="sampleFile" style="display: none;" />
    <Button htmlFor="sampleFile" component="label" type={'submit'}>Upload</Button> 
</form>
Shrroy
quelle
1

Sie können die Input- und InputLabel-Komponenten der Material-Benutzeroberfläche verwenden. Hier ist ein Beispiel, wenn Sie sie zur Eingabe von Tabellenkalkulationsdateien verwendet haben.

import { Input, InputLabel } from "@material-ui/core";

const styles = {
  hidden: {
    display: "none",
  },
  importLabel: {
    color: "black",
  },
};

<InputLabel htmlFor="import-button" style={styles.importLabel}>
    <Input
        id="import-button"
        inputProps={{
          accept:
            ".csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel",
        }}
        onChange={onInputChange}
        style={styles.hidden}
        type="file"
    />
    Import Spreadsheet
</InputLabel>
Jonri2
quelle
1

November 2020

Mit Material-UI und React Hooks

import * as React from "react";
import {
  Button,
  IconButton,
  Tooltip,
  makeStyles,
  Theme,
} from "@material-ui/core";
import { PhotoCamera } from "@material-ui/icons";

const useStyles = makeStyles((theme: Theme) => ({
  root: {
    "& > *": {
      margin: theme.spacing(1),
    },
  },
  input: {
    display: "none",
  },
  faceImage: {
    color: theme.palette.primary.light,
  },
}));

interface FormProps {
  saveFace: any; //(fileName:Blob) => Promise<void>, // callback taking a string and then dispatching a store actions
}

export const FaceForm: React.FunctionComponent<FormProps> = ({ saveFace }) => {

  const classes = useStyles();
  const [selectedFile, setSelectedFile] = React.useState(null);

  const handleCapture = ({ target }: any) => {
    setSelectedFile(target.files[0]);
  };

  const handleSubmit = () => {
    saveFace(selectedFile);
  };

  return (
    <>
      <input
        accept="image/jpeg"
        className={classes.input}
        id="faceImage"
        type="file"
        onChange={handleCapture}
      />
      <Tooltip title="Select Image">
        <label htmlFor="faceImage">
          <IconButton
            className={classes.faceImage}
            color="primary"
            aria-label="upload picture"
            component="span"
          >
            <PhotoCamera fontSize="large" />
          </IconButton>
        </label>
      </Tooltip>
      <label>{selectedFile ? selectedFile.name : "Select Image"}</label>. . .
      <Button onClick={() => handleSubmit()} color="primary">
        Save
      </Button>
    </>
  );
};

DevLoverUmar
quelle
0

Wenn Sie Funktionskomponenten von React verwenden und nicht mit Beschriftungen oder IDs arbeiten möchten, können Sie auch eine Referenz verwenden.

const uploadInputRef = useRef(null);

return (
  <Fragment>
    <input
      ref={uploadInputRef}
      type="file"
      accept="image/*"
      style={{ display: "none" }}
      onChange={onChange}
    />
    <Button
      onClick={() => uploadInputRef.current && uploadInputRef.current.click()}
      variant="contained"
    >
      Upload
    </Button>
  </Fragment>
);
Tomatentobi
quelle
0
<input type="file"
               id="fileUploadButton"
               style={{ display: 'none' }}
               onChange={onFileChange}
        />
        <label htmlFor={'fileUploadButton'}>
          <Button
            color="secondary"
            className={classes.btnUpload}
            variant="contained"
            component="span"
            startIcon={
              <SvgIcon fontSize="small">
                <UploadIcon />
              </SvgIcon>
            }
          >

            Upload
          </Button>
        </label>

Stellen Sie sicher, dass Button component = "span" hat , was mir geholfen hat.

Richard Lee
quelle