packages/@uppy/companion/src/server/controllers/s3.js
function getUploadedParts (req, res, next) {
    // @ts-ignore The `uppy` property is added by middleware before reaching here.
    const client = req.uppy.s3Client
    const { uploadId } = req.params
    const { key } = req.query

    if (typeof key !== 'string') {
      return res.status(400).json({ error: 's3: the object key must be passed as a query parameter. For example: "?key=abc.jpg"' })
    }

    let parts = []
    listPartsPage(0)

    function listPartsPage (startAt) {
      client.listParts({
        Bucket: config.bucket,
        Key: key,
        UploadId: uploadId,
        PartNumberMarker: startAt
      }, (err, data) => {
        if (err) {
          next(err)
          return
        }

        parts = parts.concat(data.Parts)

        if (data.IsTruncated) {
          // Get the next page.
          listPartsPage(data.NextPartNumberMarker)
        } else {
          done()
        }
      })
    }

    function done () {
      res.json(parts)
    }
  }
function getUploadedParts (req, res, next) {
    // @ts-ignore The `uppy` property is added by middleware before reaching here.
    const client = req.uppy.s3Client
    const { uploadId } = req.params
    const { key } = req.query

    if (typeof key !== 'string') {
      return res.status(400).json({ error: 's3: the object key must be passed as a query parameter. For example: "?key=abc.jpg"' })
    }

    let parts = []
    listPartsPage(0)

    function listPartsPage (startAt) {
      client.listParts({
        Bucket: config.bucket,
        Key: key,
        UploadId: uploadId,
        PartNumberMarker: startAt
      }, (err, data) => {
        if (err) {
          next(err)
          return
        }

        parts = parts.concat(data.Parts)

        if (data.IsTruncated) {
          // Get the next page.
          listPartsPage(data.NextPartNumberMarker)
        } else {
          done()
        }
      })
    }

    function done () {
      res.json(parts)
    }
  }
function getUploadedParts ( req , res , next ) { // @ts-ignore The `uppy` property is added by middleware before reaching here. const client = req . uppy . s3Client const { uploadId } = req . params const { key } = req . query if ( typeof key !== 'string' ) { return res . status ( 400 ) . json ( { error : 's3: the object key must be passed as a query parameter. For example: "?key=abc.jpg"' } ) } let parts = [ ] listPartsPage ( 0 ) function listPartsPage ( startAt ) { client . listParts ( { Bucket : config . bucket , Key : key , UploadId : uploadId , PartNumberMarker : startAt } , ( err , data ) => { if ( err ) { next ( err ) return } parts = parts . concat ( data . Parts ) if ( data . IsTruncated ) { // Get the next page. listPartsPage ( data . NextPartNumberMarker ) } else { done ( ) } } ) } function done ( ) { res . json ( parts ) } }
List parts that have been fully uploaded so far.

Expected URL parameters:
- uploadId - The uploadId returned from `createMultipartUpload`.
Expected query parameters:
- key - The object key in the S3 bucket.
Response JSON:
- An array of objects representing parts:
- PartNumber - the index of this part.
- ETag - a hash of this part's contents, used to refer to it.
- Size - size of this part.
List parts that have been fully uploaded so far .