I am trying to make a Jira plugin that can upload files. I am using my backend to handle the logic and it’s working fine when I try that from the postman.
But when I try the same from Jira Plugin no form-data is going in the request.
I am using the forge and custom UI for the plugin. For file upload I am using S3 and multer on backend.
I have tried by creating a react component outside the plugin code and its working from there as well
Here is upload file code
import React, { useState, useRef } from 'react';
import { Button } from 'react-bootstrap';
import Plus from '../../../../../assets/icons/Plus';
import { invokeApiRemote } from '../../../../../services/invokeApi';
import { createAttachment } from '../../../../../services/apiConfig';
const FileUpload = ({ onUpload, enableDragAndDrop, entityType, entityId }) => {
const [isDragging, setIsDragging] = useState(false);
const [error, setError] = useState(null);
const fileInputRef = useRef(null);
const handleDragOver = (e) => {
e.preventDefault();
setIsDragging(true);
};
const handleDragLeave = () => {
setIsDragging(false);
};
const handleDrop = (e) => {
e.preventDefault();
setIsDragging(false);
const files = Array.from(e.dataTransfer.files);
handleFiles(files);
};
const handleFiles = async (files) => {
console.log(files)
const formData = new FormData();
console.log('Files to upload:', files);
files && files.map((file) => {
formData.append('files', file);
});
formData.append('attachableType', entityType);
formData.append('attachableId', entityId);
console.log(formData)
try {
const response = await invokeApiRemote({
config: createAttachment(),
body: formData,
headers: {
'X-Atlassian-Token': 'no-check',
},
});
if (response) {
console.log('Attachment created successfully:', response);
// onUpload && onUpload(response);
}
} catch (error) {
console.error('Error creating attachment:', error);
setError(error.message);
}
};
const handleFileChange = (e) => {
const files = Array.from(e.target.files);
handleFiles(files);
};
const handleChooseFiles = () => {
fileInputRef.current.click();
};
return (
<div>
{enableDragAndDrop ? (
<div
onDragOver={handleDragOver}
onDragLeave={handleDragLeave}
onDrop={handleDrop}
onClick={handleChooseFiles}
style={{
border: isDragging ? '2px dashed #007bff' : '2px dashed #cccccc',
padding: '20px',
textAlign: 'center',
marginBottom: '20px',
cursor: 'pointer',
backgroundColor: isDragging ? '#f8f9fa' : 'transparent',
}}>
<p>Drag & drop or click to select files</p>
</div>
) : (
<Button
size="sm"
variant=""
className="me-2"
onClick={handleChooseFiles}>
<Plus /> Attach files
</Button>
)}
<input
type="file"
multiple
onChange={handleFileChange}
style={{ display: 'none' }}
ref={fileInputRef}
/>
{error && <p style={{ color: 'red' }}>{error}</p>}
</div>
);
};
export default FileUpload;