reactjssharepoint-onlinespfx

How to upload multiple files to an SP list item as attachments


I am creating an SP webpart using SPFX. The webpart needs to be able to upload multiple files either using one button or several buttons (one for each file).

I am trying to use this: https://pnp.github.io/pnpjs/sp/attachments/#add-multiple

But it doesn't show how to use it with React states. You see, I want to be able to save the file upload into state, so it can then be submitted using a button. That's when it is attached to the list item in SP. I then want the webpart to be able to display the attached item when the user clicks back on this item. This is why I need to use state.

I have read this: React SPFx - Adding files to SharePoint list field using PnPjs

and this: Handling file upload in Sharepoint List with React form

But they are not clear.

Can someone provide an example of how to use the pnpjs attachments with a React component class using state?


Solution

  • My test code for your reference:

        import * as React from 'react';
        import styles from './NewReactSpfx.module.scss';
        import { INewReactSpfxProps } from './INewReactSpfxProps';
        import { escape } from '@microsoft/sp-lodash-subset';
        import { Web } from "sp-pnp-js";
        import IAttachmentInfo from "sp-pnp-js";
        export default class NewReactSpfx extends React.Component<INewReactSpfxProps, any> {
          public constructor(props) {
            super(props);
            this.state = {     
              fileInfos: null
            };
          }
          public render(): React.ReactElement<INewReactSpfxProps> {
            return (
              <div className={styles.newReactSpfx}>
                <div className={styles.container}>
                  <div className={styles.row}>
                    <div className={styles.column}>
                      <span className={styles.title}>Welcome to SharePoint!</span>
                      <p className={styles.subTitle}>Customize SharePoint experiences using Web Parts.</p>
                      <p className={styles.description}>{escape(this.props.description)}</p>
                      <a href="https://aka.ms/spfx" className={styles.button}>
                        <span className={styles.label}>Learn more</span>
                      </a>
                    </div>
                    <input type="file" multiple={true} id="file" onChange={this.addFile.bind(this)} />
                    <input type="button" value="submit" onClick={this.upload.bind(this)} />
                  </div>
                </div>
              </div>
            );
          }
          private addFile(event) {
            //let resultFile = document.getElementById('file');
            let resultFile = event.target.files;
            console.log(resultFile);
            let fileInfos = [];
            for (var i = 0; i < resultFile.length; i++) {
              var fileName = resultFile[i].name;
              console.log(fileName);
              var file = resultFile[i];
              var reader = new FileReader();
              reader.onload = (function(file) {
                 return function(e) {
                      //Push the converted file into array
                       fileInfos.push({
                          "name": file.name,
                          "content": e.target.result
                          });
                        }
                 })(file);
              reader.readAsArrayBuffer(file);
            }
            this.setState({fileInfos});
            console.log(fileInfos)
          }
          private upload() {
        
        
            let {fileInfos}=this.state;
        
            
            console.log(this.props)
            let web = new Web(this.props.context.pageContext.web.absoluteUrl);
            web.lists.getByTitle("testn").items.getById(2).attachmentFiles.addMultiple(fileInfos);
          }
        }
    

    You could get full project here:

    https://github.com/Amos-IT/SharePoint-FrameWork-Demos/tree/master/NewReactSPFX

    Updated:

    private _onSubmit = (ev) => {
        this.setState({
          FormStatus: 'Submitted',
        }, () => {
          sp.web.lists.getByTitle("PanelMeetings").items.add({
            Title: this.state.Title,
            StartDate: this.state.PanelStartDate,
    
          }).then(r=>{
            r.item.attachmentFiles.add(this.state.fileInfos)
          });
        });