I uploading file with Upload Manually in Ant Design but it not able to show preview image as base64. I want to show preview image base64 as picture card when I picked image from browser. How I can fix it?
My code upload:
const FormPost = () => {
const [fileList, setFileList] = useState([]);
const [uploading, setUploading] = useState(false);
const onFinish = (values) => {
console.log('Success:', values);
};
const onFinishFailed = (errorInfo) => {
console.log('Failed:', errorInfo);
};
const normFile = (e) => {
console.log('Upload event:', e);
if (Array.isArray(e)) {
return e;
}
return e?.fileList;
};
const uploadProps = {
onRemove: (file) => {
const index = fileList.indexOf(file);
const newFileList = fileList.slice();
newFileList.splice(index, 1);
setFileList(newFileList);
},
beforeUpload: (file) => {
setFileList([...fileList, file]);
return false;
},
listType: 'picture-card',
fileList,
};
return (
<Form layout="vertical" name="new-post" onFinish={onFinish} onFinishFailed={onFinishFailed} autoComplete="off">
<Form.Item label="Upload" valuePropName="fileList" getValueFromEvent={normFile}>
<Upload {...uploadProps}>
<div>New photo</div>
</Upload>
</Form.Item>
</Form>
);
};
I had the same question in my mind some days ago. The key is to use ["thumbUrl"] attribute of the file user selected. This is how I solved it:
If it is how you have Upload component defined:
<Upload
action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
listType="picture-card"
fileList={params.fileList}
onChange={params.onChange}
onPreview={params.onPreview}
>
{params.fileList.length === 0 && '+ Upload'}
</Upload>
It should be the Image component you are trying to show the user:
<Image
width={'80%'}
height={'60%'}
src={params.fileList[0]["thumbUrl"]}
/>
Related
I am pretty new to React, and the only CRUD functionality I have done has been in MVC.net, so I am pretty lost here and none of the tutorials I am finding seem to be the situation I have going on...or maybe I am just misunderstanding them. The tips I got with my initial question helped, but I am still no getting it to work, so hopefully now I have supplies enough info to help other help me. I did no include all of the input fields because their are like 15 and it was just redundant.
I am pulling up the modal using this onClick event:
onClick={()=> {handleEditModal(item)}}
modalFunctions.js
// Modal Functionality
export function ModalFunctions() {
const [selectedRecord, setSelectedRecord] = useState([]);
const [openModal, setOpenModal] = useState(false);
const handleEditModal = item =>{
setOpenModal(true)
setSelectedRecord(item)
}
return {
selectedRecord,
setSelectedRecord,
openModal,
setOpenModal,
handleEditModal,
handleDetailModal
}
}
// Form Functionality
export function FormFunctions(validateOnChange = false, validate) {
const [values, setValues] = useState('');
const [errors, setErrors] = useState({});
const handleInputChange = e => {
const { name, value } = e.target
setValues({
...values,
[name]: value
})
if (validateOnChange)
validate({ [name]: value })
}
return {errors, handleInputChange, setErrors, setValues, values}
}
DataTable.js
// Imported Modal Functions
const {
selectedRecord,
openModal,
setOpenModal,
handleEditModal,
handleDetailModal
} = ModalFunctions();
const baseURL = 'http://localhost:8080/api/tanks';
// Fetch Data
useEffect(() => {
const fetchData = async () =>{
setLoading(true);
try {
const {data: response} = await axios.get(baseURL);
setTableData(response);
} catch (error) {
console.error(error.message);
}
setLoading(false);
};
fetchData();
}, [baseURL, setTableData, setLoading]);
// The Modal
return(
<Modal
title={ "Editing: " + (selectedRecord.tankName) }
openModal={openModal}
setOpenModal={setOpenModal}
>
<TankEdit
selectedRecord={selectedRecord}
setOpenModal={setOpenModal}
openModal={openModal}
/>
</Modal>
)
TankEdit.js
export function TankEdit(props) {
const { baseURL, openModal, selectedRecord, setOpenModal, setTableData } = props;
const validate = (fieldValues = item) => {
let temp = { ...errors }
if ('tankName' in fieldValues)
temp.tankName = fieldValues.tankName ? "" : "This field is required."
setErrors({
...temp
})
if (fieldValues === values)
return Object.values(temp).every(x => x === " ")
}
const {
values,
setValues,
errors,
setErrors,
handleInputChange,
} = FormFunctions(true, validate);
useEffect(() => {
if (selectedRecord !== null)
setValues({
...selectedRecord
})
}, [selectedRecord, setValues])
function editRecord() {
axios.put(`${baseURL}`, {
title: "Success",
body: "The record had been successfully updated"
}).then ((response) => {setTableData(response.data);})
}
const handleSubmit = e => {
e.preventDefault()
if (validate()) {
editRecord(values);
}
setOpenModal(false)
}
const item = values; // used for easier referencing (matches table item)
return (
<Form onSubmit={handleSubmit} open={openModal}>
<Grid>
<Controls.Input
name="tankName"
label="Tank Name"
value={item.tankName}
onChange={handleInputChange}
error={errors.tankName}
/>
</Grid>
<Grid>
<Controls.Button
type="submit"
text="Submit"
/>
<Controls.Button
text="Cancel"
color="default"
onClick={()=>{setOpenModal(false)}}
/>
</Grid>
</Form>
)
}
Input.js
export default function Input(props) {
const { error=null, label, name, onChange, value, ...other } = props;
return (
<TextField
variant="outlined"
label={label}
name={name}
value={value}
defaultValue=''
onChange={onChange}
{...other}
{...(error && {error:true,helperText:error})}
/>
)
}
My company is only wanting a Read and an Update function, since Creating and Deletion will be handled another ways, so this is my final hangup. I think I am close, but I am missing something.
Can anyone point me in the right direction?
THANKS!!!!
If you want to write an update request you would use axios.put to send the data to your back-end.
In your handleSubmit function you do:
let response = await axios.put('http://-------/api/tanks', { name: 'tank' });
(The second parameter is an object that needs to contain all the form data fields)
Also make sure you call e.preventDefault() in the handleSubmit function so you don't accidentally navigate elsewhere.
Then you will update your database or whatever using your back-end.
for update you should use put or patch method
and you should send id of item you want to update in request url.
I insert 2 example here.
this is for put:
const res = await axios.put('/api/article/123', {
title: 'Making PUT Requests with Axios',
status: 'published'
});
this is for patch:
const res = await axios.patch('/api/article/123', {
title: 'Making PUT Requests with Axios',
status: 'published'
});
// I want to use the upload component of antDesing to accept only video files.
const beforeUpload = (file) => {
const isVideo = file.type === 'video/*'; //using (video/*) is not working here to accept any video file.
console.log('fle type', file.type);
if (!isVideo) {
message.error('You can only upload video file!');
}
const isLt10M = file.size / 1024 / 1024 < 10;
if (!isLt10M) {
message.error('Video must smaller than 10MB!');
}
return isVideo && isLt10M;
};
const handleChange = (info) => {
console.log('info', info);
};
render(
<Upload beforeUpload={beforeUpload} onChange={handleChange}>
<Button icon={<UploadOutlined />}>Click to Upload</Button>
</Upload>
)
//let me know if there is any way to sort the issue
Try it with regex:
const regex = /video\/.*/g;
const isVideo = regex.test(file.type);
I think the title is self-explanatory. What am I doing wrong below? What I want to achieve is getting the text out of a photo, right after the user selects a photo.
The error I get is:
createWorker.js:173 Uncaught Error: RuntimeError: null function or function signature mismatch
What am I doing wrong?
const { createWorker } = require("tesseract.js");
const [file,setFile] = useState();
const worker = createWorker({
logger: (m) => console.log(m),
});
const doOCR = async (image) => {
await worker.load();
await worker.loadLanguage("eng");
await worker.initialize("eng");
const {
data: { text },
} = await worker.recognize(image);
// } = await worker.recognize('https://tesseract.projectnaptha.com/img/eng_bw.png');
console.log(text);
setOcr(text);
};
const [ocr, setOcr] = useState("Recognizing...");
useEffect(() => {
file ? doOCR(file) : console.log('no file selected yet!');
}, [file]);
const getFile = (e) => {
console.log("Upload event:", e);
if (e) {
if (Array.isArray(e)) setFile(e[0]);
setFile(e)
}
}
....
<p>{ocr}</p> /* this only displays "Recognizing..." */
<Form.Item
name="uploadedPhoto"
label="Upload your photo scan"
getValueFromEvent={getFile}
// rules={[{ required: true }]}>
<Input type="file"
// onChange={onImageUpload}
/>
</Form.Item>
Solved it by doing it like this instead of the above (I applied the function to the onChange of the Input itself, not the Form.Item element)
const handleFileSelected = (e) => {
const files = Array.from(e.target.files);
setFile(files[0]);
};
<Input type="file" onChange={handleFileSelected} />
Here i'm trying to add multiple files to upload, but it is replacing in to new one and the response value is also showing empty. i dont understand what i'm doing wrong here thanks in advance
const [question, setQuestion] = React.useState('');
const [fileImage, setFileImage] = React.useState([]);
const handleChange = (event) => {
setQuestion(event.target.value);
}
const handleSelectChange = (event) => {
setFileImage(event.target.files);
}
addQuizDetails() {
const Questions = question;
const fileImages = fileImage;
const headers = {
"Content-Type": "multipart/form-data"
}
var formData = new FormData();
formData.append("image", fileImages);
formData.append("question",question )
axios
.post("http://localhost:4000/api/quiz/addQuiz",formData,headers)
.then(response => {
if (response.data.message) {
alert(response.data.message)
}
else {
alert("failed")
}
})
}
}
<TextField className={classes.content} onChange={handleChange} label="Question" variant="outlined" />
<input
type="file"
onChange={handleSelectChange}
multiple />
<div className={classes.button}>
<Button className={classes.submit} variant="contained" onClick={addQuizDetails}>Submit</Button>
</div>
Try below code by using spread operator for array:
const handleSelectChange = (event) => {
const selectedFiles = event.target.files
setFileImage([...fileImage, ...selectedFiles]);
}
I want to test a React component where certificate file is uploaded and the result of file can be shown in a text area.
I am still learning writing unit test and here facing difficulty to mock FileReader, readAsText and onloadend.
I have read few examples but they do not work as expected. Any guidance would be helpful
Thanks
Cert Component
export default function Cert() {
const fileInputRef = useRef();
function handleEvent(obj, event) {
var event = new Event(event, { target: obj, bubbles: true });
return obj ? obj.dispatchEvent(event) : false;
}
let handleChangeFile = (file) => {
let fileData = new FileReader();
fileData.readAsText(file);
fileData.onloadend = () => {
let el = document.getElementById('cert');
el.value = event.target.result;
handleEvent(el, 'input');
if (fileInputRef.current) {
fileInputRef.current.value = '';
}
};
fileData.onerror = function () {
console.log(fileData.error);
};
};
return (
<CheckboxWithOptions name="int" label='app'>
<Field
component={ExpandingTextareaField}
name="certificate"
label='Upload Certificate *'
isRequired
validate={required}
id="cert"
/>
<div>
<Button
label='Upload file'
type="button"
appearance="brand"
size="large"
onClick={() => {
fileInputRef.current.click();
}}
data-typeId="test"
/>
<input
style={{
opacity: 0,
position: 'fixed',
top: 0,
left: 0,
width: 0,
}}
type="file"
accept=".cert"
ref={fileInputRef}
onChange={(e) => handleChangeFile(e.target.files[0])}
data-testid="testinput"
/>
</div>
}
Cert.test.js
it('upload file to show in textarea ', async () => {
const file = new File(['dummy'], 'test.cert', { type: 'cert' })
render(
<div>
<label htmlFor="file-uploader">Upload file:</label>
<input id="file-uploader" type="file" onChange={(e) => handleChangeFile('e')} />
</div>,
)
const { getByLabelText } = render(<TestComponent />);
await waitForElementToBeRemoved(() => screen.getByText(/loading/i));
expect(getByLabelText("CheckBox").value).toBe("false");
fireEvent.click(screen.getByLabelText("CheckBox"))
const input = screen.getByLabelText(/Upload file/i)
fireEvent.click(input)
userEvent.upload(input, file)
await waitFor(() => expect(handleChangeFile).toBeCalledTimes(1)); // working fine till here
jest.spyOn(global, "FileReader")
.mockImplementation(function () {
readAsText = jest.fn();
});
fireEvent.change(input, {
target: {
files: [file]
}
});
expect(FileReader).toHaveBeenCalled(); // not working
// test the FileReader and textarea
})
Had the same issue with checking some side effect that should be invoked on FileReader.onload, so I just ended up setting a short pause after triggering the event (I'm using enzyme):
const pauseFor = milliseconds => new Promise(resolve => setTimeout(resolve, milliseconds));
...
wrapper.find('.upload-box').simulate('drop', someMockedDropEvent);
// set pause was the only way to make reader.onload to fire
await pauseFor(100);
expect(something).toEqual(something)