I am developing a chat application with Laravel and React. I want to send pictures in the chat, but the sent pictures do not appear or are distorted. I’ve been dealing with this problem for a long time.
First of all, I send information about the file to the data column in my database.and I brodcasting my event.
public function uploadFile(Request $request, $to)
{
$from = $request->input('from');
$file = $request->file('file');
$from = User::find($from);
$to = User::find($to);
if ($from && $to && $file) {
$filePath = $file->store('message-files');
$fileName = basename($filePath);
$log = new MessageLog;
$log->channel = 'agent-' . $from->id . '-' . $to->id;
$log->from = $from->id;
$log->to = $to->id;
$log->save();
$log->setData([
'file_path' => $filePath,
'file_name' => $fileName,
'file_orginal_name' => $file->getClientOriginalName(),
'file_size' => $file->getSize(),
]);
$log->load('from');
$log->load('to');
broadcast(new AgentFileEvent($from, $to, $file));
return response(['result' => $log]);
}
if (!$file) {
return response(['message' => 'no file uploaded'], 400);
}
}
public function fileDownload(Request $request, $name)
{
if (Storage::fileExists('message-files/' . $name)) {
return Storage::download('message-files/' . $name);
}
return response()->json([
'error' => 'File ' . $name . ' not found!',
]);
}
Burada formdata’ya gönderdiğim görselleri axios request ile çağırıyorum. Ve addMessage’a ile resulta gönderiyorum.
const sendFile = (file) => {
let url, formData;
formData=new FormData();
formData.append('to',active.to.id)
formData.append('from',active.from.id)
formData.append('file',file)
if (formData) {
axios.post(Route.get('upload-file', {
'to': active.to.id,
}), formData)
.then(result => {
if (result.data.result !== undefined) {
addMessage(result.data.result);
}
})
.catch(error => {
console.log("ERROR:", error);
});
}
}
The purpose of using addMessage was actually to receive messages, but I also used it to receive images. Could the problem originate from here?
Messages and images received via the OpenChat method need to be listed.
const openChat = (active) => {
setActive(active);
Storage.set('active', active);
markMessageAsRead( active.to.id, active.from.id );
loadMessages();
console.log('channel:', 'agent-'+active.to.id+'-'+active.from.id);
console.log('listen:', '.agent-'+active.from.id+'-'+active.to.id);
window.Echo.private('agent-'+active.to.id+'-'+active.from.id).listen('.agent-'+active.from.id+'-'+active.to.id, (e) => {
addMessage(e);
console.log(e);
loadMessages();
});
window.Echo.join(active.channel);
}
I used these two methods for sending messages.
const loadMessages = () =>
{
if(!isObjectEmpty(active)){
let url, data;
if(active.type == 'private'){
url = Route.get('chat-get-agent')
data = {
from: active.from.id,
to: active.to.id
};
}
if(active.type == 'channel'){
url = Route.get('chat-get-channel', {'channel': active.data.name})
data = {};
}
if(url !== undefined && data !== undefined){
axios.post(url, data)
.then(response => {
if(response.data.result !== undefined) setMessages(response.data.result.reverse())
})
.catch(error => { console.log("ERROR:: ", error.response.data); });
}
}
}
const sendMessage = (message) => {
if(!isObjectEmpty(active)){
let url, data;
if(active.type == 'private'){
url = Route.get('chat-agent-event', {'to': active.to.id})
data = {
from: active.from.id,
to: active.to.id,
message: message,
from_details: active.from,
to_details: active.to
};
}
if(active.type == 'channel'){
url = Route.get('chat-channel-event', {'channel': active.data.name})
data = {
from: active.from.id,
message: message,
from_details: active.from,
channel: active.data
};
}
if(url !== undefined && data !== undefined){
axios.post(url, data)
.then(result => {
if(result.data.result !== undefined) addMessage(result.data.result);
})
.catch(error => { console.log("ERROR:: ", error); });
}
axios.post(Route.get('send-notification'), { 'to':active.to.id, 'data': data });
}
}
I created this component to send messages and images.
class MessageSender extends React.Component {
static contextType = ChatContext
constructor(props) {
super(props);
this.state = {
message: "",
result: "",
active: {},
file: "",
type: "message",
};
this.setMessage = this.setMessage.bind(this);
this.sendMessage = this.sendMessage.bind(this);
this._handleKeyDown = this._handleKeyDown.bind(this);
this.handleFileChange = this.handleFileChange.bind(this);
this.sendFile = this.sendFile.bind(this);
this.fileInputRef = React.createRef();
}
setMessage(event) {
this.setState({
message: event.target.value
})
}
sendMessage() {
if (this.state.type == 'message') {
this.context.sendMessage(this.state.message)
this.setState({ message: "" });
globalScrollRef.scrollTo(0, globalScrollRef.scrollHeight);
}
if (this.state.type == 'file') {
this.context.sendFile(this.state.file)
this.setState({ file: '' });
globalScrollRef.scrollTo(0, globalScrollRef.scrollHeight);
}
}
handleFileChange(event) {
this.setState({
file: event.target.files[0],
type: "file",
});
}
handleDefaultState() {
this.setState({
type: "message",
});
}
_handleKeyDown(event) {
if (event.key === 'Enter') {
event.preventDefault();
this.sendMessage()
}
}
sendFile() {
this.context.sendFile(this.state.file)
this.setState({ file: "" });
globalScrollRef.scrollTo(0, globalScrollRef.scrollHeight);
}
render() {
return (
<div className="nk-chat-editor">
<div className="nk-chat-editor-upload ms-n1">
<a href="#" className="btn btn-sm btn-icon btn-trigger text-primary toggle-opt" data-target="chat-upload"><em className="icon ni ni-plus-circle-fill" onClick={() => { this.handleDefaultState() }}></em></a>
<div className="chat-upload-option" data-content="chat-upload">
<ul className="">
<li>
<label htmlFor="fileInput">
<em className="icon ni ni-img-fill"></em>
</label>
<input
type="file"
id="fileInput"
name='file'
onChange={this.handleFileChange}
/>
</li>
<li><a href="#"><em className="icon ni ni-camera-fill"></em></a></li>
<li><a href="#"><em className="icon ni ni-mic"></em></a></li>
<li><a href="#"><em className="icon ni ni-grid-sq"></em></a></li>
</ul>
</div>
</div>
<div className="nk-chat-editor-form">
<div className="form-control-wrap">
<textarea className="form-control form-control-simple no-resize" rows="1" id="default-textarea" placeholder="Type your message..." onChange={this.setMessage} onKeyDown={this._handleKeyDown} value={this.state.message}></textarea>
</div>
</div>
<ul className="nk-chat-editor-tools g-2">
<li>
<button className="btn btn-round btn-primary btn-icon" onClick={() => { this.sendMessage() }}><em className="icon ni ni-send-alt"></em></button>
</li>
</ul>
</div>
);
}
}
This section is the component I use to list incoming messages and images.
class Message extends React.Component {
static contextType = ChatContext;
constructor(props) {
super(props);
this.state = {
message: (this.props.message !== undefined ? this.props.message : ""),
is_me: false
};
}
render() {
const { session } = this.context;
const { message } = this.state;
let date = "";
let is_me = false;
if (message.from.id === session.id) {
is_me = true;
}
if (message.created_at) {
date = moment(message.created_at).fromNow();
}
if (message.data !== null && message.data !== undefined) {
try {
var data = JSON.parse(message.data);
var downloadUrl = Route.get('download-file', { 'name': data.file_name });
message.message = <img src={downloadUrl} style={{ maxSize: "100px" }} />
} catch (error) {
//console.error("Error parsing message data:", error);
message.message = ""
}
}
return (
<div className={`chat ${is_me ? 'is-me' : 'is-you'}`}>
{is_me ? null : (
<div className="chat-avatar">
<div className="user-avatar bg-purple">
<span>{message.from.name.charAt(0)}{message.from.surname.charAt(0)}</span>
</div>
</div>
)}
<div className="chat-content">
<div className="chat-bubbles">
<div className="chat-bubble">
<div className="chat-msg">{message.message}</div>
</div>
</div>
<ul className="chat-meta">
<li>{message.from.name}</li>
<li>{date}</li>
{is_me && message.is_read && <li><i className="far fa-check-circle" style={{ color: 'green' }}></i></li>}
</ul>
</div>
</div>
);
}
}
enter image description here
enter image description here
The image looks like this. Thank you very much in advance for your help.
user24487676 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.