无法从React应用程序将文件上传到s3

问题描述 投票:0回答:1

我在从 React 应用程序将 pdf 上传到 s3 存储桶时遇到问题。 当我尝试推送文件时出现错误,但错误不是很清楚。

这就是我在 Flask 应用程序上生成 presigned_url 的方式:

from flask import Flask, jsonify, request
import boto3
import datetime
def create_file_upload_url_controller():
    try:
        s3_client = boto3.client('s3')
        print('create_file_upload_url_controller()')
        user_id = str(request.user.id)

        file_name = f"{user_id}_{datetime.datetime.utcnow()}"
        bucket_name = "docwise-large-files-dev"
        print(f'file_name: {file_name}')

        # Generate pre-signed URL for upload
        presigned_url = s3_client.generate_presigned_url(
            'put_object',
            Params={'Bucket': bucket_name, 'Key': file_name},
            ExpiresIn=3600,  # URL valid for 1 hour
            HttpMethod="PUT"
        )
        
        print(f'presigned_url:  {presigned_url}')

        return jsonify({'upload_url': presigned_url, 'file_name': file_name})

    except Exception as e:
        print(f'e: {e}')
        return jsonify({'error': str(e)}), 500

这是从用户收集文件的组件::

// FileUpload.js
import React, { useEffect, useState } from 'react';
import { connect } from 'react-redux';
import { addFile } from '../../../../../../actions/filesActions';
import { useNavigate, useParams } from 'react-router-dom';

const FileUpload = ({ onFileChange, addFile, conversation_id,files }) => {
  const { chatId } = useParams();

  useEffect( ()=>{
  },[files])

  const handleFileChange = (event) => {
    const selectedFiles = event.target.files;
    for (let i = 0; i < selectedFiles.length; i++) {
      const file = selectedFiles[i];
      const fileDetails = {
        conversation_id: chatId,
        file: file,
      };
      addFile(fileDetails);
    }
  };



  return (
    <div>
      <input type="file"  onChange={handleFileChange} />
    </div>
  );
};

const mapStateToProps = (state) => ({
  files: state.files.files
});

const mapActionsToProps = {
  addFile,
};

export default connect(mapStateToProps, mapActionsToProps)(FileUpload);

这是将文件推送到 aws s3::

的操作
// filesActions.js

export const ADD_PDF = 'ADD_PDF';
export const ADD_PDF_SUCCESS = 'ADD_PDF_SUCCESS';
export const ADD_PDF_FAIL = 'ADD_PDF_FAIL';
export const DELETE_PDF = 'DELETE_PDF';
export const UPDATE_PDF = 'UPDATE_PDF';

// /api/file/create_file_upload_url_url



let baseUrl;
if (process.env.MODE === 'local') {
  baseUrl = `/api/file/`;
} else {
  baseUrl = `${process.env.REACT_APP_BACKEND_URL}/api/file/`;
}


export const addFile = (pdfDetails) => async (dispatch, getState) => {
  try {
    const { token } = getState().auth;

    const createFileUploadURLResponse = await fetch(`${baseUrl}create_file_upload_url`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${token}`,
      },
      body: null,
    });

    if (createFileUploadURLResponse.error != null) {
      console.log('error: ', createFileUploadURLResponse.error);
      return dispatch({
        type: ADD_PDF_FAIL,
        payload: createFileUploadURLResponse.error,
      });
    }

    const createFileUploadURLResponseData = await createFileUploadURLResponse.json();

    console.log(`createFileUploadURLResponseData:  ${createFileUploadURLResponseData.upload_url}`);
    console.log(`key : ${createFileUploadURLResponseData.file_name}`)

    console.log('pdfDetails.file:   ',pdfDetails.file);


    console.log('before uploading file to s3')

    const uploadFileResponse = await fetch(`${createFileUploadURLResponseData.upload_url}`, {
      method: 'PUT',
      headers: {
        'Content-Type': pdfDetails.file.type,  // Change to file's actual MIME type
        'Key': `${createFileUploadURLResponseData.file_name}`,
      },
      body: pdfDetails.file,
    });
    const uploadFileResponseData = await uploadFileResponse.json();

    console.log(`uploadFileResponseData:  ${JSON.stringify(uploadFileResponseData)}`);



  } catch (error) {
    console.log('error: ', error);
    return null;
  }
};

这是我收到的错误::

filesActions.js:52     PUT https://docwise-large-files-dev.s3.amazonaws.com/Juan_Casas_Resume.pdf?AWSAccessKeyId=AKIAYNCJFQSXTCQHFGR3&Signature=GTb89cRSPxDQhp0TmTfuggDKPfc%3D&Expires=1692137811 403 (Forbidden)

我找到了这篇文章,但没有帮助:: https://fullstackdojo.medium.com/s3-upload-with-presigned-url-react-and-nodejs-b77f348d54cc

SignatureDoesNotMatch:拒绝 SignedURL

这是网络选项卡

python flask amazon-s3 amazon-elastic-beanstalk
1个回答
0
投票

服务器和前端的标头需要相同。

我需要在后端使用这些标头;:

            Params={'Bucket': bucket_name, 'Key': file_name, 'ContentType': "application/pdf",},

我缺少内容类型

© www.soinside.com 2019 - 2024. All rights reserved.