【问题标题】:How to save files into AWS using signedURLs and ReactJS?如何使用 signedURLs 和 ReactJS 将文件保存到 AWS?
【发布时间】:2020-06-30 22:22:52
【问题描述】:

我正在尝试将带有常规文本输入的图像附加到我的表单中,以便提交到我的 MongoDB。

这是我创建帖子的功能:

  const [postData, setPostData] = useState({
    text: '',
    images: null,
    postedto: auth && auth.user.data._id === userId ? null : userId
  });

  const { text, images, postedto } = postData;

  const handleChange = name => e => {
    setPostData({ ...postData, [name]: e.target.value, images: e.target.files });
  };

  const createPost = async e => {
    e.preventDefault();
    await addPost(postData, setUploadPercentage);
  };

从那里我开始我的行动 addPost;在这个函数上,我调用了两个 API 路由:

// @route       POST api/v1/posts
// @description Add post
// @access      Private
// @task        DONE
export const addPost = (formData, setUploadPercentage) => async dispatch => {
  try {
    // ATTACH FILES
    let fileKeys = [];

    for(let file of formData.images) {
      const uploadConfig = await axios.get(`${API}/api/v1/uploads/getS3url?type=${file.type}`);
      
      await axios.put(uploadConfig.data.url, file, {
        headers: {
          'Content-Type': file.type
        }
      });

      fileKeys.push(uploadConfig.data.key);
    }

    console.log(fileKeys);

    // INSERT NEW BLOG
    const config = {
      headers: {
        'Content-Type': 'multipart/form-data; application/json'
      },
      onUploadProgress: ProgressEvent => {
        setUploadPercentage(
          parseInt(Math.round(ProgressEvent.loaded * 100) / ProgressEvent.total)
        );
        // Clear percentage
        setTimeout(() => setUploadPercentage(0), 10000);
      }
    };

    formData.images = fileKeys;

    const res = await axios.post(`${API}/api/v1/posts`, formData, config);
    
    dispatch({
      type: ADD_POST,
      payload: res.data
    });

    dispatch(setAlert('Post Created', 'success'));
  } catch (err) {
    const errors = err.response && err.response.data.errors;

    if (errors) {
      errors.forEach(error => dispatch(setAlert(error.msg, 'danger')));
    }

    dispatch({
      type: POST_ERROR,
      payload: { msg: err.response && err.response.statusText, status: err.response && err.response.status }
    });
  }
};

我的 getS3url 函数看起来就像这样:

exports.uploadFile = asyncHandler(async (req, res, next) => {
  const { type } = req.query;
  const fileExtension = type.substring(type.indexOf('/') + 1);
  const key = `${process.env.WEBSITE_NAME}-${req.user._id}-${
    req.user.email
  }-${Date.now().toString()}.${fileExtension}`;

  const params = {
    Bucket: process.env.AWS_BUCKET_NAME,
    Key: key,
    ContentType: type
  };

  s3.getSignedUrl(`putObject`, params, (err, url) => {
    if (err) {
      return next(
        new ErrorResponse(
          `There was an error with the files being uploaded`,
          500
        )
      );
    }

    return res.status(201).json({ success: true, key: url });
  });
});

我想指出,每篇文章可能有多个图像文件,并且该函数应该为每个文件返回一个签名URL;假设我上传了两个文件,然后我应该检索两个 URL 以便将它们附加到我的帖子中。

我确信我管理状态以提交数据的方式没有任何问题,因为它总是返回我在 console.log(postData) 上使用时所期望的内容,甚至显示文件。

现在我假设问题出在我的操作上,尤其是 /// INSERT NEW BLOG 注释之前的代码,因为当我 console.log(fileKeys) 没有返回任何内容时,甚至没有错误/未定义/null .....我的意思是什么都没有!

当与单个文件一起使用时,我的 uploadFile 工作正常......不是真的,因为是的,它返回“假定”上传文件的 URL,但是当我进入我的 AWS 控制台/存储桶时,什么都没有......但那是它自己的帖子。

我需要什么帮助?

好吧,我正在尝试使用 signedURL 将一个/多个文件上传到我的 AWS 中,以将它们作为字符串返回并将它们附加到我的帖子中。我的操作文件有问题吗?

谢谢!!。

【问题讨论】:

  • 你需要使用putObject上传文件到s3。上传成功后,即可获得签名网址。
  • 是的,我知道我的应用程序已经返回了 URL,但是对于一个苍蝇,我希望为每个文件返回一个字符串

标签: javascript node.js reactjs amazon-web-services pre-signed-url


【解决方案1】:

对于我的情况,我一直在遍历图像并生成签名 URL 并返回它们,因为 s3 不支持一次多个文件的签名 URL 选项。

【讨论】:

  • 别担心老兄,我早就解决了。你可以看看我的回答。
【解决方案2】:

最后我找到了自己的解决方案,这里是:

export const addPost = (formData, images, setUploadPercentage) => async dispatch => {
  try {

    let fileKeys = [];

    for(let i = 0; i < images.length; i++) {
      
      /// STEP 3
      const token = localStorage.getItem("xAuthToken");
      api.defaults.headers.common["Authorization"] = `Bearer ${token}`

      const uploadConfig = await api.get(`/uploads/getS3url?name=${images[i].name}&type=${images[i].type}&size=${images[i].size}`);

      // STEP 1
      delete api.defaults.headers.common['Authorization'];

      await api.put(uploadConfig.data.postURL, images[i], {
        headers: {
          'Content-Type': images[i].type
        }
      });

      fileKeys.push(uploadConfig.data.getURL);
    }

    // INSERT NEW BLOG
    const config = {
      onUploadProgress: ProgressEvent => {
        setUploadPercentage(
          parseInt(Math.round(ProgressEvent.loaded * 100) / ProgressEvent.total)
        );
        setTimeout(() => setUploadPercentage(0), 10000);
      }
    };

    // STEP 2
    const token = localStorage.getItem("xAuthToken");
    api.defaults.headers.common["Authorization"] = `Bearer ${token}`

    const res = await api.post(`/posts`, {...formData, images: fileKeys}, config);
    
    dispatch({
      type: ADD_POST,
      payload: res.data
    });

    dispatch(setAlert('Post Created', 'success'));
  } catch (err) {
    const errors = err.response && err.response.data.errors;

    if (errors) {
      errors.forEach(error => dispatch(setAlert(error.msg, 'danger')));
    }

    dispatch({
      type: POST_ERROR,
      payload: { msg: err.response && err.response.statusText, status: err.response && err.response.status }
    });
  }
};

【讨论】:

    猜你喜欢
    • 2020-07-28
    • 1970-01-01
    • 1970-01-01
    • 2019-08-21
    • 1970-01-01
    • 2023-03-10
    • 2021-02-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多