admin管理员组

文章数量:1389762

I am making a chat app as a project in school, and I am trying to add a onClick that runs a function, that uses socket-io-file-upload, to run a prompt function. From the socket-io-file-upload docs. When this method is called, the user will be prompted to choose a file to upload.

JavaScript:

document.getElementById("file_button").addEventListener("click", instance.prompt, false);
HTML:

<button id="file_button">Upload File</button>

Basically I am not sure how I would go about connected the back-end which is being ran separate on how I would be able to use socket-io, in the react front-end as far as using the file-upload..

Here are the files I have right now related to this ponent in some way - FYI - Using Styled Components

Front-End :

My Reducer (Maybe relevant) -

import React from "react";
import io from "socket.io-client";
export const CTX = React.createContext();

const initState = {
  selectedChannel: "general",
  socket: io(":3001"),
  user: "RandomUser",
  allChats: {
    general: [''],
    channel2: [{ from: "user1", msg: "hello" }],
  },
};
const reducer = (state, action) => {
  console.log(action);
  switch (action.type) {
    case "SET_CHANNEL_NAME":
      const newChannelName = action.payload;
      return {
        ...state,
        allChats: {
          ...state.allChats,
          [newChannelName]: [{from: "ChatBot", msg: "Wele to a new chatroom!"}]
        }
      }
    case "CREATE_CHANNEL":
      return {
        ...state,
        allChats: {
          ...state.allChats,
          newChannel: [ {from: "chatbot", msg: "Wele to a new chatroom! Type away!"}]
        }
      };
    case "SET_USER_NAME":
      return {
        ...state,
        user: action.payload,
      };
    case "SET_SELECTED_CHANNEL":
      return {
        ...state,
        selectedChannel: action.payload,
      };
    case "RECEIVE_MESSAGE":
      const { from, msg, channel } = action.payload;
      return {
        ...state,
        allChats: {
          ...state.allChats,
          [channel]: [...state.allChats[state.selectedChannel], { from, msg }],
        },
      };
    default:
      return state;
  }
};

// const sendChatAction = (value) => {
//     socket.emit('chat message', value);
// }

export const Store = (props) => {
  const [state, dispatch] = React.useReducer(reducer, initState);

  const myDispatch = (type, payload) => {
    if (typeof type === "object" && type !== null) {
      dispatch(type);
    }
    dispatch({ type, payload });
  };

  return (
    <CTX.Provider value={{ state, dispatch: myDispatch }}>
      {props.children}
    </CTX.Provider>
  );
};

ChatBox.js -

import React from "react";
import styled from "styled-ponents";
import Sidebar from "../Sidebar";
import io from 'socket.io-client'
import UserMessage from "../UserMessage";
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faPlus } from '@fortawesome/free-solid-svg-icons'
import InputAddon from '../InputAddon'



import { CTX } from '../Store'


const ChatBox = () => {
  const [textValue, changeTextValue] = React.useState('');

  const { state, dispatch } = React.useContext(CTX);
  console.log(state.user)
  React.useEffect(() => {
    console.log(state.user)

    state.socket.on('message', function (msg) {
      console.log("chat message recieved")
      dispatch('RECEIVE_MESSAGE', msg);
    })
  }, [])



  const onKeyPressHandler = (e) => {
    if (e.key === 'Enter') {
      e.preventDefault();
      console.log("PRESSED")
      state.socket.emit('sent message', { from: state.user, msg: textValue, channel: state.selectedChannel });
      dispatch('RECEIVE_MESSAGE', { from: state.user, msg: textValue, channel: state.selectedChannel });
      changeTextValue('')
    }
  }

  const onChangeHandler = e => {
    changeTextValue(e.target.value);
  }


  return (

    <Layout>
      <Sidebar />
      <Wrapper>
        <InnerBoxWrapper>
          <InnerBox>
            <UserMessage />
            <InputWrapper>
              <InputAddons id="InputAddon">
                <FontAwesomeIcon icon={faPlus} onClick={InputAddon}></FontAwesomeIcon>
              </InputAddons>
              <input
                label="Send a chat"
                onChange={onChangeHandler}
                value={textValue}
                onKeyPress={onKeyPressHandler}
              />
            </InputWrapper>
          </InnerBox>
        </InnerBoxWrapper>
      </Wrapper>
    </Layout>
  )
}

InputAddon.js -

import React from 'react';

const InputAddon = () => {
    console.log('clicked')
}

export default InputAddon;

BACKEND -

www.js -

/**
 * Module dependencies.
 */

var app = require('../app');
var debug = require('debug')('cryptidbackend:server');
var http = require('http').createServer(app);
const io = require('socket.io')(http);
const siofu = require('socketio-file-upload')
const cors = require('cors');
app.use(cors());
// Socket.io 

io.on('connection', function (socket) {
  const uploader = new siofu(socket);
  uploader.prompt(document.getElementById("InputAddon"))
  uploader.listen(socket)
  socket.on('sent message', function (msg) {
    console.log('message' + ' : ' + JSON.stringify(msg))
    socket.broadcast.emit('message', msg);
  })
})


/**
 * Get port from environment and store in Express.
 */
http.listen(3001, function () {
  console.log('listening on 3001')
})

app.js -

const siofu = require('socketio-file-upload')
const app = express()

const cors = require("cors");
const bodyParser = require("body-parser");
const logger = require("morgan");
const session = require("express-session");
const FileStore = require("session-file-store")(session);
const upload = require("express-fileupload");

app.use(siofu.router)

app.use(upload());
console.log("Server Started!");

app.use(logger("dev"));

app.use(cors());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(
  session({
    resave: false,
    secret: "hello",
    saveUninitialized: true,
    is_logged_in: false,
  })
);

const indexRouter = require("./routes/index");
app.use("/", indexRouter);

const usersRouter = require('./routes/users');
app.use('/users', usersRouter);

module.exports = app;

If you have any questions, or can give me any tips please do I am only about 5 months into my coding career so I still have a lot to learn.

I am making a chat app as a project in school, and I am trying to add a onClick that runs a function, that uses socket-io-file-upload, to run a prompt function. From the socket-io-file-upload docs. When this method is called, the user will be prompted to choose a file to upload.

JavaScript:

document.getElementById("file_button").addEventListener("click", instance.prompt, false);
HTML:

<button id="file_button">Upload File</button>

Basically I am not sure how I would go about connected the back-end which is being ran separate on how I would be able to use socket-io, in the react front-end as far as using the file-upload..

Here are the files I have right now related to this ponent in some way - FYI - Using Styled Components

Front-End :

My Reducer (Maybe relevant) -

import React from "react";
import io from "socket.io-client";
export const CTX = React.createContext();

const initState = {
  selectedChannel: "general",
  socket: io(":3001"),
  user: "RandomUser",
  allChats: {
    general: [''],
    channel2: [{ from: "user1", msg: "hello" }],
  },
};
const reducer = (state, action) => {
  console.log(action);
  switch (action.type) {
    case "SET_CHANNEL_NAME":
      const newChannelName = action.payload;
      return {
        ...state,
        allChats: {
          ...state.allChats,
          [newChannelName]: [{from: "ChatBot", msg: "Wele to a new chatroom!"}]
        }
      }
    case "CREATE_CHANNEL":
      return {
        ...state,
        allChats: {
          ...state.allChats,
          newChannel: [ {from: "chatbot", msg: "Wele to a new chatroom! Type away!"}]
        }
      };
    case "SET_USER_NAME":
      return {
        ...state,
        user: action.payload,
      };
    case "SET_SELECTED_CHANNEL":
      return {
        ...state,
        selectedChannel: action.payload,
      };
    case "RECEIVE_MESSAGE":
      const { from, msg, channel } = action.payload;
      return {
        ...state,
        allChats: {
          ...state.allChats,
          [channel]: [...state.allChats[state.selectedChannel], { from, msg }],
        },
      };
    default:
      return state;
  }
};

// const sendChatAction = (value) => {
//     socket.emit('chat message', value);
// }

export const Store = (props) => {
  const [state, dispatch] = React.useReducer(reducer, initState);

  const myDispatch = (type, payload) => {
    if (typeof type === "object" && type !== null) {
      dispatch(type);
    }
    dispatch({ type, payload });
  };

  return (
    <CTX.Provider value={{ state, dispatch: myDispatch }}>
      {props.children}
    </CTX.Provider>
  );
};

ChatBox.js -

import React from "react";
import styled from "styled-ponents";
import Sidebar from "../Sidebar";
import io from 'socket.io-client'
import UserMessage from "../UserMessage";
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faPlus } from '@fortawesome/free-solid-svg-icons'
import InputAddon from '../InputAddon'



import { CTX } from '../Store'


const ChatBox = () => {
  const [textValue, changeTextValue] = React.useState('');

  const { state, dispatch } = React.useContext(CTX);
  console.log(state.user)
  React.useEffect(() => {
    console.log(state.user)

    state.socket.on('message', function (msg) {
      console.log("chat message recieved")
      dispatch('RECEIVE_MESSAGE', msg);
    })
  }, [])



  const onKeyPressHandler = (e) => {
    if (e.key === 'Enter') {
      e.preventDefault();
      console.log("PRESSED")
      state.socket.emit('sent message', { from: state.user, msg: textValue, channel: state.selectedChannel });
      dispatch('RECEIVE_MESSAGE', { from: state.user, msg: textValue, channel: state.selectedChannel });
      changeTextValue('')
    }
  }

  const onChangeHandler = e => {
    changeTextValue(e.target.value);
  }


  return (

    <Layout>
      <Sidebar />
      <Wrapper>
        <InnerBoxWrapper>
          <InnerBox>
            <UserMessage />
            <InputWrapper>
              <InputAddons id="InputAddon">
                <FontAwesomeIcon icon={faPlus} onClick={InputAddon}></FontAwesomeIcon>
              </InputAddons>
              <input
                label="Send a chat"
                onChange={onChangeHandler}
                value={textValue}
                onKeyPress={onKeyPressHandler}
              />
            </InputWrapper>
          </InnerBox>
        </InnerBoxWrapper>
      </Wrapper>
    </Layout>
  )
}

InputAddon.js -

import React from 'react';

const InputAddon = () => {
    console.log('clicked')
}

export default InputAddon;

BACKEND -

www.js -

/**
 * Module dependencies.
 */

var app = require('../app');
var debug = require('debug')('cryptidbackend:server');
var http = require('http').createServer(app);
const io = require('socket.io')(http);
const siofu = require('socketio-file-upload')
const cors = require('cors');
app.use(cors());
// Socket.io 

io.on('connection', function (socket) {
  const uploader = new siofu(socket);
  uploader.prompt(document.getElementById("InputAddon"))
  uploader.listen(socket)
  socket.on('sent message', function (msg) {
    console.log('message' + ' : ' + JSON.stringify(msg))
    socket.broadcast.emit('message', msg);
  })
})


/**
 * Get port from environment and store in Express.
 */
http.listen(3001, function () {
  console.log('listening on 3001')
})

app.js -

const siofu = require('socketio-file-upload')
const app = express()

const cors = require("cors");
const bodyParser = require("body-parser");
const logger = require("morgan");
const session = require("express-session");
const FileStore = require("session-file-store")(session);
const upload = require("express-fileupload");

app.use(siofu.router)

app.use(upload());
console.log("Server Started!");

app.use(logger("dev"));

app.use(cors());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(
  session({
    resave: false,
    secret: "hello",
    saveUninitialized: true,
    is_logged_in: false,
  })
);

const indexRouter = require("./routes/index");
app.use("/", indexRouter);

const usersRouter = require('./routes/users');
app.use('/users', usersRouter);

module.exports = app;

If you have any questions, or can give me any tips please do I am only about 5 months into my coding career so I still have a lot to learn.

Share Improve this question asked May 1, 2020 at 22:50 BlueBlue 2511 gold badge9 silver badges28 bronze badges
Add a ment  | 

4 Answers 4

Reset to default 5 +25

In order to upload file from frontend, what you need to do is to create an instance of socket-file-upload on frontend in a useEffect inside ChatBox ponent.

Also you need to create a dummy hidden input on which you can simulate click when Upload button is clicked and also the input on which you can listen on

Small snippet code that you need to add

  const fileRef = useRef(null);
  useEffect(() => {
     const siofu = new SocketIOFileUpload(state.socket);
     // call listen on input and pass the hidden input ref
     siofu.listenOnInput(fileRef.current);
  }, [state.socket])

  const InputAddon = () => {
     // Trigger click on fileRef input
     fileRef.current.click();
  }

Full ponent code with input

import SocketIOFileUpload from 'socketio-file-upload';
const ChatBox = () => {
  const [textValue, changeTextValue] = React.useState('');

  const { state, dispatch } = React.useContext(CTX);
  console.log(state.user)
  React.useEffect(() => {
    console.log(state.user)

    state.socket.on('message', function (msg) {
      console.log("chat message recieved")
      dispatch('RECEIVE_MESSAGE', msg);
    })
  }, [])





  const onKeyPressHandler = (e) => {
    if (e.key === 'Enter') {
      e.preventDefault();
      console.log("PRESSED")
      state.socket.emit('sent message', { from: state.user, msg: textValue, channel: state.selectedChannel });
      dispatch('RECEIVE_MESSAGE', { from: state.user, msg: textValue, channel: state.selectedChannel });
      changeTextValue('')
    }
  }

  const onChangeHandler = e => {
    changeTextValue(e.target.value);
  }
  const fileRef = useRef(null);
  useEffect(() => {
     const siofu = new SocketIOFileUpload(state.socket);
     // call listen on input and pass the hidden input ref
     siofu.listenOnInput(fileRef.current);
  }, [state.socket])

  const InputAddon = () => {
     // Trigger click on fileRef input
     fileRef.current.click();
  }

  return (

    <Layout>
      <Sidebar />
      <Wrapper>
        <InnerBoxWrapper>
          <InnerBox>
            <UserMessage />
            <InputWrapper>
              <InputAddons id="InputAddon">
                <FontAwesomeIcon icon={faPlus} onClick={InputAddon}></FontAwesomeIcon>
              </InputAddons>
               <input
                ref={fileRef}
                label="file-picker"
                type="file"
                style={{display: 'none'}}
              />
              <input
                label="Send a chat"
                onChange={onChangeHandler}
                value={textValue}
                onKeyPress={onKeyPressHandler}
              />
            </InputWrapper>
          </InnerBox>
        </InnerBoxWrapper>
      </Wrapper>
    </Layout>
  )
}

In the backend code you need to create a express server and add sockiofileUpload router to it

var app = require('../app');
var debug = require('debug')('cryptidbackend:server');
const socketio = require('socket.io');

/**
 * Get port from environment and store in Express.
 */
app.listen(3001, function () {
  console.log('listening on 3001')
})



var io = socketio.listen(app);

// Socket.io 

io.sockets.on('connection', function (socket) {
    const uploader = new siofu(socket);
    uploader.listen(socket)
    uploader.dir = "/srv/uploads";
    uploader.listen(socket);

    // Do something when a file is saved:
    uploader.on("saved", function(event){
        console.log(event.file);
    });

    // Error handler:
    uploader.on("error", function(event){
        console.log("Error from uploader", event);
    });
})

app.js

const siofu = require('socketio-file-upload')
const app = express()

const cors = require("cors");
const bodyParser = require("body-parser");
const logger = require("morgan");
const session = require("express-session");
const FileStore = require("session-file-store")(session);

app.use(siofu.router)

console.log("Server Started!");

app.use(logger("dev"));

app.use(cors());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(
  session({
    resave: false,
    secret: "hello",
    saveUninitialized: true,
    is_logged_in: false,
  })
);

const indexRouter = require("./routes/index");
app.use("/", indexRouter);

const usersRouter = require('./routes/users');
app.use('/users', usersRouter);

first of all this part of the code is in backend and in backend there is no document or window.which means document.getElementById wont work here.

 io.on('connection', function (socket) {
  const uploader = new siofu(socket);
  uploader.prompt(document.getElementById("InputAddon"))
  uploader.listen(socket)
  socket.on('sent message', function (msg) {
    console.log('message' + ' : ' + JSON.stringify(msg))
    socket.broadcast.emit('message', msg);
  })
})

then there is no upload file location/dir is define.

you can see the example

express-fileupload

app.use(fileUpload({
    useTempFiles : true,
    tempFileDir : '/tmp/'
}));

socketio-file-upload

io.on("connection", function(socket){
    var uploader = new siofu();
    uploader.dir = "/path/to/save/uploads";  ***//upload directory***
    uploader.listen(socket);
});

so what i will suggest you is go throught the link mention below and update your code.

https://www.npmjs./package/express-fileupload

https://github./sffc/socketio-file-upload

Uncaught TypeError: SocketIOFileUpload is not a constructor

import {SocketIOFileUpload} from "socketio-file-upload";

useEffect(() => {
    const siofu = new SocketIOFileUpload(socket);
    // call listen on input and pass the hidden input ref
 }, [socket])

but :

Uncaught TypeError: SocketIOFileUpload is not a constructor

identify the image file from your destination location then use

public static byte[] readBytesFromFile(File file) throws IOException 
{
       InputStream is = new FileInputStream(file);

       // Get the size of the file
       long length = file.length();

       // You cannot create an array using a long type.
       // It needs to be an int type.
       // Before converting to an int type, check
       // to ensure that file is not larger than Integer.MAX_VALUE.
       if (length > Integer.MAX_VALUE) 
       {
           is.close();
         throw new IOException("Could not pletely read file " + file.getName() + " as it is too long (" + length + " bytes, max supported " + Integer.MAX_VALUE + ")");

       }

       // Create the byte array to hold the data
       byte[] bytes = new byte[(int)length];

       // Read in the bytes
       int offset = 0;
       int numRead = 0;
       while (offset < bytes.length && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) 
       {
           offset += numRead;
       }

       // Ensure all the bytes have been read in
       if (offset < bytes.length) 
       {
           is.close();
           throw new IOException("Could not pletely read file "   +file.getName());
       }

       // Close the input stream and return bytes
       is.close();
       return bytes;
}

store image data into byte array.

Then, mention your destination location and apply

It will run.

本文标签: javascriptHow would I go about uploading a image file using SocketIOStack Overflow