Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PUT vs POST and Zero Byte Files #58

Open
justinkhill-emorysolutions opened this issue May 20, 2021 · 2 comments
Open

PUT vs POST and Zero Byte Files #58

justinkhill-emorysolutions opened this issue May 20, 2021 · 2 comments

Comments

@justinkhill-emorysolutions
Copy link

justinkhill-emorysolutions commented May 20, 2021

We're using a python / django backend to generate the presigned url as described here: https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html#S3.Client.generate_presigned_url

We're getting an error from S3 upon upload complaining that the signature doesn't match. We discovered that if we change the bucket loader code to do a PUT instead of a POST that we could get past that error.

New problem though. The files are being created in S3 but they are all zero bytes.

What are we missing here? Our next step is to try the boto3 method to generate a presigned post instead of a presigned url.
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html#S3.Client.generate_presigned_post
Hope that works, but it has a bunch of formfields and other return data besides just the URL that I'm not sure the bucket loader component can handle? If anyone has any other suggestions, please comment.

@ypicard
Copy link

ypicard commented Jun 15, 2021

Same here, I would like to be able to use presigned urls for PUT requests. Any updates on this?

@justinkhill-emorysolutions
Copy link
Author

justinkhill-emorysolutions commented Jun 15, 2021

we abandoned this component and did it on our own using code similar to this

                  <b-collapse id="collapse-1" class="mt-2">
                    <b-card id="upload">
                      <p class="card-text">
                        <b-row>
                        <b-col cols="6">
                          <label>
                              <input class="mb-2" type="file" id="file" ref="file" v-on:change="handleFileUpload()"/>
                          </label>
                        </b-col>
                        <b-col cols="4">
                          <progress id="progress" max="100" :value.prop="uploadPercentage"></progress>
                        </b-col>
                        <b-col cols="2">
                          <b-button :disabled="!file || is_uploading" class="float-right mb-2" size="sm" variant="success" v-on:click="submitFile()">
                            <span v-if="!is_uploading">Submit</span>
                            <span v-else>
                              <b-spinner small label="Small Spinner"></b-spinner>
                            </span>
                          </b-button>
                        </b-col>
                        </b-row>
                      </p>
                    </b-card>
                  </b-collapse>

    handleError (error) {
      this.$emit('uploadError', error)
    },
    handleFileUpload () {
      this.file = this.$refs.file.files[0]
    },
    submitFile () {
      this.is_uploading = true
      const uninterceptedAxiosInstance = axios.create()
      this.presignedPutURL(this.file).then(() => {
        if (this.s3_files_names.includes(this.file.name)) {
          this.showToast('Upload Failed: Duplicate File',
            'A file with the name ' + this.file.name + ' already exists!',
            'warning'
          )
          this.is_uploading = false
          this.uploadPercentage = 0
        } else {
          uninterceptedAxiosInstance.put(this.presigned_put_url, this.file,
            {
              headers: {
                'Content-Type': 'multipart/form-data'
              },
              onUploadProgress: function (progressEvent) {
                this.uploadPercentage = parseInt(Math.round((progressEvent.loaded / progressEvent.total) * 100))
              }.bind(this)
            }
          ).then(response => {
            if (!this.s3_files_names.includes(this.file.name) && response.status === 200) {
              this.$emit('s3Update')
              this.showToast('Upload Successful',
                this.file.name + ' has been successfully uploaded!'
              )
            }
            this.is_uploading = false
            this.uploadPercentage = 0
            this.$refs.file.value = ''
            this.file = ''
          }, this.handleError)
        }
      })
    },
    presignedPutURL (file) {
      const fileName = file.name
      return apiService.post('get-upload-url', { file_name: fileName })
        .then(response => {
          this.presigned_put_url = response.data
        }, this.handleError)
    },
    def post(self, request):
        file_name = request.data['file_name']

        put_url = boto3.client('s3', region_name=settings.AWS_S3_REGION_NAME).generate_presigned_url(
            ClientMethod='put_object',
            Params={'Bucket': settings.AWS_S3_BUCKET_NAME, 'Key': f'uploads/{file_name}'},
            ExpiresIn=60)

        return Response(put_url)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants