【问题标题】:Upload csv file to S3 bucket from static webpage从静态网页上传 csv 文件到 S3 存储桶
【发布时间】:2021-10-14 19:15:13
【问题描述】:

我正在尝试创建一个上传网页以将 csv 文件放入 S3 存储桶中。 我按照他们网站上的教程进行操作。 https://aws.amazon.com/blogs/compute/uploading-to-amazon-s3-directly-from-a-web-or-mobile-application/

我修改了接受参数文件名的方法。一切正常,但找不到将文件从 html 上传到 S3 的方法。

我通常是后端 pythonist 和 google 来更改此网页/js,但我没有设法解决它。

我尝试从 reader.readAsDataURL(file) 更改为 reader.readAsText(file, 'UTF-8'),还将 data:image/jpg 更改为 data:text/csv 或 text/plain 但在线需要“包括”返回“长度:假”

console.log('length: ', e.target.result.includes('data:image/jpeg'))

您可以在下面找到我的新代码,如果您可以将我重定向到一些关于如何发送 csv 文件以及 API 中的“?文件名=原始文件名”的线索,我真的很爱你 :)。

<!DOCTYPE html>
<html>
<head>
    <title>Upload file to S3</title>
    <script src="https://unpkg.com/vue"></script>
    <script src="https://unpkg.com/axios@0.2.1/dist/axios.min.js"></script>
</head>
<body>
<div id="app">
    <h1>S3 Uploader Test</h1>

    <div v-if="!file">
        <h2>Select a file</h2>
        <input type="file" @change="onFileChange">
    </div>
    <div v-else>
        <img :src="file" />
        <button v-if="!uploadURL" @click="removeFile">Remove file</button>
        <button v-if="!uploadURL" @click="uploadFile">Upload file</button>
    </div>
    <h2 v-if="uploadURL">Success! File uploaded to bucket.</h2>
</div>

<script>
    const MAX_FILE_SIZE = 1000000

    /* ENTER YOUR ENDPOINT HERE */

    const API_ENDPOINT = 'https://<smth>.execute-api.eu-central-1.amazonaws.com/uploads'
    // e.g. https://ab1234ab123.execute-api.us-east-1.amazonaws.com/uploads

    new Vue({
        el: "#app",
        data: {
            file: '',
            uploadURL: ''
        },
        methods: {
            onFileChange (e) {
                let files = e.target.files || e.dataTransfer.files
                if (!files.length) return
                this.createFile(files[0])
            },
            createFile (file) {
                // var image = new Image()
                let reader = new FileReader()
                reader.readAsText(file, 'UTF-8');
                reader.onload = (e) => {
                    //console.log(e.target.result)
                    console.log('length: ', e.target.result.includes('data:/csv'))
                     if (!e.target.result.includes('data:text/csv')) {
                       return alert('Wrong file type', e.target.result)
                    }
                    if (e.target.result.length > MAX_FILE_SIZE) {
                        return alert('File is loo large.')
                    }
                    this.file = e.target.result
                }
                // reader.readAsDataURL(file)
            },
            removeFile: function (e) {
                console.log('Remove clicked')
                this.file = ''
            },
            uploadFile: async function (e) {
                console.log('Upload clicked')
                // Get the presigned URL
                const response = await axios({
                    method: 'GET',
                    url: API_ENDPOINT+'?filename='+'last.csv'
                })
                console.log('Response: ', response)
                console.log('Uploading: ', this.file)
                let binary = atob(this.file.split(',')[1])
                let array = []
                for (var i = 0; i < binary.length; i++) {
                    array.push(binary.charCodeAt(i))
                }
                let blobData = new Blob([new Uint8Array(array)], {type: 'text/csv'})
                console.log('Uploading to: ', response.uploadURL)
                const result = await fetch(response.uploadURL, {
                    method: 'PUT',
                    body: blobData
                })
                console.log('Result: ', result)
                // Final URL for the user doesn't need the query string params
                this.uploadURL = response.uploadURL.split('?')[0]
            }
        }
    })
</script>
<style type="text/css">
    body {
        background: #20262E;
        padding: 20px;
        font-family: sans-serif;
    }
    #app {
        background: #fff;
        border-radius: 4px;
        padding: 20px;
        transition: all 0.2s;
        text-align: center;
    }
    #logo {
        width: 100px;
    }
    h2 {
        font-weight: bold;
        margin-bottom: 15px;
    }
    h1, h2 {
        font-weight: normal;
        margin-bottom: 15px;
    }
    a {
        color: #42b983;
    }
    img {
        width: 30%;
        margin: auto;
        display: block;
        margin-bottom: 10px;
    }
</style>
</body>
</html>

【问题讨论】:

    标签: javascript amazon-web-services csv amazon-s3 static-html


    【解决方案1】:

    感谢@smac2020 的指导,仍然很有用,我没有机会进一步研究它。 经过几个小时的 vue.js 学习,制作了这个工作代码。

    <!DOCTYPE html>
    <html>
    <head>
        <title>Upload file to S3</title>
        <script src="https://unpkg.com/vue"></script>
        <script src="https://unpkg.com/axios@0.2.1/dist/axios.min.js"></script>
    </head>
    <body>
    <div id="app">
        <h1>S3 Uploader Test</h1>
    
        <div v-if="!file">
            <h2>Select a file</h2>
            <input type="file" @change="onFileChange">
        </div>
        <div v-else>
            <div>File {{ name }} loaded </div>
            <button v-if="!uploadURL" @click="removeFile">Remove file</button>
            <button v-if="!uploadURL" @click="uploadFile">Upload file</button>
        </div>
        <h2 v-if="uploadURL">Success! File uploaded to bucket.</h2>
    </div>
    
    <script>
        const MAX_FILE_SIZE = 1000000
    
        /* ENTER YOUR ENDPOINT HERE */
        const API_ENDPOINT = 'https://<smth>.execute-api.eu-central-1.amazonaws.com/uploads'
        // e.g. https://ab1234ab123.execute-api.us-east-1.amazonaws.com/uploads
    
        new Vue({
            el: "#app",
            data: {
                file: '',
                uploadURL: '',
                name: ''
            },
            methods: {
                onFileChange (e) {
                    let files = e.target.files || e.dataTransfer.files
                    if (!files.length) return
                    this.createFile(files[0])
                },
                createFile (file) {
                    let reader = new FileReader()
                    this.name = file.name
                    console.log(this.name)
                    reader.readAsText(file, 'UTF-8');
                    reader.onload = (e) => {
                        if (e.target.result.length > MAX_FILE_SIZE) {
                            return alert('File is loo large.')
                        }
                        this.file = e.target.result
                    }
                },
                removeFile: function (e) {
                    console.log('Remove clicked')
                    this.file = ''
                },
                uploadFile: async function (e) {
                    console.log('Upload clicked', this.name)
                    // Get the presigned URL
                    const response = await axios({
                        method: 'GET',
                        url: API_ENDPOINT+'?filename='+this.name
                    })
                    console.log('Response: ', response)
                    let blobData = new Blob([this.file], {type: 'text/csv'})
                    console.log('Uploading to: ', response.uploadURL)
                    const result = await fetch(response.uploadURL, {
                        method: 'PUT',
                        body: blobData
                    })
                    console.log('Result: ', result)
                    // Final URL for the user doesn't need the query string params
                    this.uploadURL = response.uploadURL.split('?')[0]
                }
            }
        })
    </script>
    <style type="text/css">
        body {
            background: #20262E;
            padding: 20px;
            font-family: sans-serif;
        }
        #app {
            background: #fff;
            border-radius: 4px;
            padding: 20px;
            transition: all 0.2s;
            text-align: center;
        }
        #logo {
            width: 100px;
        }
        h2 {
            font-weight: bold;
            margin-bottom: 15px;
        }
        h1, h2 {
            font-weight: normal;
            margin-bottom: 15px;
        }
        a {
            color: #42b983;
        }
        img {
            width: 30%;
            margin: auto;
            display: block;
            margin-bottom: 10px;
        }
    </style>
    </body>
    </html>

    【讨论】:

      【解决方案2】:

      在创建使用脚本标签的静态网站时,请考虑使用 AWS SDK for JavaScript 将对象放入 Amazon S3 存储桶中。 适用于 JavaScript 开发工具包版本 3 的 AWS 开发人员指南中介绍了上传对象。

      Uploading photos to Amazon S3 from a browser

      (当然对于您的用例,将照片文件替换为 CSV 文件)。

      【讨论】:

      • 感谢重定向。几个小时后 :) 学习了更多 Vue.JS 并解决了我的问题。 > 完全放弃 '''"result.includes('"'''' - 我想是与图像文件有关的东西。 > 在 vue.js 变量定义中创建一个变量并从 file.name 中获取名称 > 和 blobData我定义为 '''let blobData = new Blob([this.file], {type: 'text/csv'})'''
      猜你喜欢
      • 2018-06-08
      • 2018-02-07
      • 1970-01-01
      • 2020-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-23
      • 2015-03-12
      相关资源
      最近更新 更多