最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Handling multiple image upload with React JS & Laravel - Stack Overflow

programmeradmin1浏览0评论

I want to upload multiple images to the database by using axios in reactjs to send the data from client-side to server-side and handle the image upload with laravel in the server-side. My problem is that whenever i try to handle multiple images at the server-side, it doesn't work.

This is my code.

CLIENT-SIDE (ReactJS)

CONSTRUCTOR:

constructor(props){
        super(props);
        this.state = {
            id: "upload-photo",
            imageArray: [],
            body: '',
            posts: [],
            // image: []
        };
        this.handleSubmit = this.handleSubmit.bind(this);
        this.handleBodyChange = this.handleBodyChange.bind(this);
    }

HanleFileChange:

handleFileChange(e){
        if (e.target.files) {
            const files = Array.from(e.target.files);

            const promises = files.map(file => {
                return (new Promise((resolve, reject) => {
                    const reader = new FileReader();
                    reader.addEventListener('load', (ev) => {
                        resolve(ev.target.result);
                    });
                    reader.addEventListener('error', reject);
                    reader.readAsDataURL(file);
                }))
            });

            Promise.all(promises).then(images => {
                this.setState({
                    imageArray: images
                })
            }, error => { console.error(error); });
        }
        if (this.props.onChange !== undefined) {
            this.props.onChange(e);
        }
    }

HandleSubmitChange:

handleSubmit(e) {
        e.preventDefault();
        // this.postData();
        const formData = new FormData();
        this.state.imageArray.forEach((image_file) => {
             formData.append('file[]', image_file);
        });
        formData.append('body', this.state.body);
        for (let pair of formData.entries()) {
            console.log(pair[0]+ ', ' + pair[1]);
        }
        axios.post('/posts', formData)
            .then(response => {
            this.setState({
                posts: [response.data]
            })
        });
        this.setState({
            body: ''
        });
    }

SERVER-SIDE (LARAVEL)

public function create(Request $request, Post $post) {
        $data = [];
        if ($request->get('file')) {
            foreach ($request->get('file') as $file) {
                $name = time() . '.' . explode('/', explode(':', substr($file, 0, strpos($file, ';')))[1])[1];
                \Image::make($file)->save(public_path('images/') . $name);
                array_push($data, $name);
            }
        }
        $image = json_encode($data);
        // create post
        $createdPost = $request->user()->posts()->create([
            'body' => $request->body,
            'image' => $image
        ]);
        // return the response
        return response()->json($post->with('user')->find($createdPost->id));
    }

I expect all uploaded images to be saved to the database. Instead, it throws an error: Invalid argument supplied for foreach(). Therefore, if i remove, the foreach() loop and upload only one image, it saves the image successfully. How can I make use of the loop to save multiple images?

UPDATE
This question has been answered in the ments below by @DelenaMalan. I updated the code in this question so that others searching for answers related to this problem can use the code to solve their problem.

I want to upload multiple images to the database by using axios in reactjs to send the data from client-side to server-side and handle the image upload with laravel in the server-side. My problem is that whenever i try to handle multiple images at the server-side, it doesn't work.

This is my code.

CLIENT-SIDE (ReactJS)

CONSTRUCTOR:

constructor(props){
        super(props);
        this.state = {
            id: "upload-photo",
            imageArray: [],
            body: '',
            posts: [],
            // image: []
        };
        this.handleSubmit = this.handleSubmit.bind(this);
        this.handleBodyChange = this.handleBodyChange.bind(this);
    }

HanleFileChange:

handleFileChange(e){
        if (e.target.files) {
            const files = Array.from(e.target.files);

            const promises = files.map(file => {
                return (new Promise((resolve, reject) => {
                    const reader = new FileReader();
                    reader.addEventListener('load', (ev) => {
                        resolve(ev.target.result);
                    });
                    reader.addEventListener('error', reject);
                    reader.readAsDataURL(file);
                }))
            });

            Promise.all(promises).then(images => {
                this.setState({
                    imageArray: images
                })
            }, error => { console.error(error); });
        }
        if (this.props.onChange !== undefined) {
            this.props.onChange(e);
        }
    }

HandleSubmitChange:

handleSubmit(e) {
        e.preventDefault();
        // this.postData();
        const formData = new FormData();
        this.state.imageArray.forEach((image_file) => {
             formData.append('file[]', image_file);
        });
        formData.append('body', this.state.body);
        for (let pair of formData.entries()) {
            console.log(pair[0]+ ', ' + pair[1]);
        }
        axios.post('/posts', formData)
            .then(response => {
            this.setState({
                posts: [response.data]
            })
        });
        this.setState({
            body: ''
        });
    }

SERVER-SIDE (LARAVEL)

public function create(Request $request, Post $post) {
        $data = [];
        if ($request->get('file')) {
            foreach ($request->get('file') as $file) {
                $name = time() . '.' . explode('/', explode(':', substr($file, 0, strpos($file, ';')))[1])[1];
                \Image::make($file)->save(public_path('images/') . $name);
                array_push($data, $name);
            }
        }
        $image = json_encode($data);
        // create post
        $createdPost = $request->user()->posts()->create([
            'body' => $request->body,
            'image' => $image
        ]);
        // return the response
        return response()->json($post->with('user')->find($createdPost->id));
    }

I expect all uploaded images to be saved to the database. Instead, it throws an error: Invalid argument supplied for foreach(). Therefore, if i remove, the foreach() loop and upload only one image, it saves the image successfully. How can I make use of the loop to save multiple images?

UPDATE
This question has been answered in the ments below by @DelenaMalan. I updated the code in this question so that others searching for answers related to this problem can use the code to solve their problem.

Share Improve this question edited Apr 9, 2019 at 16:58 Israel Obanijesu asked Apr 9, 2019 at 15:38 Israel ObanijesuIsrael Obanijesu 6961 gold badge14 silver badges28 bronze badges 4
  • 1 Just a quick guess: JSON.stringify the files array before appending it to formData – Thomas Commented Apr 9, 2019 at 16:13
  • 1 Try this on the frontend side: this.state.imageArray.forEach((image_file) => { formData.append('file[]', image_file); }); – D Malan Commented Apr 9, 2019 at 16:19
  • Thanks @DelenaMalan. That worked like a charm :) – Israel Obanijesu Commented Apr 9, 2019 at 16:43
  • Good to hear @IsraelObanijesu I'll post it as an answer. – D Malan Commented Apr 10, 2019 at 7:51
Add a ment  | 

1 Answer 1

Reset to default 10

In your frontend side you could use formData.append('file[]', image_file) to add your image files to the file array in the form data, for example:

this.state.imageArray.forEach((image_file) => {
    formData.append('file[]', image_file);
});
发布评论

评论列表(0)

  1. 暂无评论