Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/image/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python中如何使用签名URL上传到Google存储桶?_Python_Google App Engine_Flask_Google Cloud Storage_Signed Url - Fatal编程技术网

在Python中如何使用签名URL上传到Google存储桶?

在Python中如何使用签名URL上传到Google存储桶?,python,google-app-engine,flask,google-cloud-storage,signed-url,Python,Google App Engine,Flask,Google Cloud Storage,Signed Url,我能够创建签名的URL,只需要知道创建后如何处理它们 有几个例子使用Javascript通过签名URL上传,但我在Python中找不到任何例子。我正在尝试使用签名URL作为解决Google App Engine对我的Flask应用程序施加的32 MB限制的方法 这是我的python app.py脚本(这里不是我应用程序的全部功能,只是尝试成功上传到我的bucket): 下面是我用来创建签名URL的函数: def generate_upload_signed_url_v4(bucket_name,

我能够创建签名的URL,只需要知道创建后如何处理它们

有几个例子使用Javascript通过签名URL上传,但我在Python中找不到任何例子。我正在尝试使用签名URL作为解决Google App Engine对我的Flask应用程序施加的32 MB限制的方法

这是我的python app.py脚本(这里不是我应用程序的全部功能,只是尝试成功上传到我的bucket):

下面是我用来创建签名URL的函数:

def generate_upload_signed_url_v4(bucket_name, blob_name):

    storage_client = storage.Client()
    bucket = storage_client.bucket(bucket_name)
    blob = bucket.blob(blob_name)

    url = blob.generate_signed_url(
        version="v4",
        # This URL is valid for 15 minutes
        expiration=datetime.timedelta(minutes=15),
        # Allow GET requests using this URL.
        method="PUT",
        content_type="application/octet-stream",
    )
    print(url)
    return url

generate_upload_signed_url_v4(bucket_name, 'file.csv')

下面是my home.html:

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <title>test upload</title>
</head>
<body>
    <h3> test upload </h3>

    <form method="POST" action="/" enctype="multipart/form-data">
        <p>Upload file1 below</p>
        <input type="file" name="file1"> 
        <br>
        <br>
        <p>Upload file2 below</p>
        <input type="file" name="file2">
        <br>
        <br>
        <input type="submit" value="upload">
    </form>


</body>
</html>

生成的签名URL是否以html形式存在?是否需要进入我的上传文件功能

最后,当我将已签名的URL粘贴到浏览器中时,会显示以下错误:


<Error>
<Code>MalformedSecurityHeader</Code>
<Message>Your request has a malformed header.</Message>
<ParameterName>content-type</ParameterName>
<Details>Header was included in signedheaders, but not in the request.</Details>
</Error>

这是我的第一个SO问题,所以如果它结构不好,我很抱歉。我是超级迷茫,是新来的GCP。我已经搜索了一段时间了,但没有找到Python/Flask的用例,在这个用例中,我可以看到签名URL是如何合并到文件上传过程中的

同样,我正在Google App Engine flex上构建一个webapp,需要有签名的URL来绕过32MB的文件上传限制

更新

在意识到我只需要对签名的URL发出请求后,我找到了签名的URL组件

下面是我在App Engine中加载的新脚本(为下面的代码段导入并删除“ifname=main..”


上面的代码仍然抛出413实体太大的错误。我想这是因为即使我正在创建签名的URL,我的“帖子”也会通过应用程序引擎进行。我需要如何重新安排/我做错了什么?代码需要如何构造才能让用户通过签名url直接上传到Google云存储,避免触发413实体过大错误?

一旦在服务器上生成签名url,您只需将其发送回客户端并使用它上传文件。例如,您可以使用普通的fetch put请求发送文件数据,或者我更喜欢使用axios:

await axios.put(url, file);

此处的url是已签名的url。您可能希望将文件作为

发送。您可以尝试两种方法吗:1。生成签名url时使用路径作为blob
generate\u upload\u signed\u url\u v4(bucket\u name,“/upload/”)
。第二,你能把url方法从PUT改为POST吗?如果其中一个或两个解决了您的问题,请告诉我。在发现我只需向我创建的签名URL发出请求后,我确实实现了这一点。然而,它只在我的本地机器上工作,并且仍然在AppEngine上出现413错误,因为我测试的文件大于32MB。根据我所读到的,签名的URL应该直接上传到Google云存储,然后在上传之后,它们通过应用程序引擎触发应用程序逻辑。然而,我不知道这是如何做到的。当我尝试时,我仍然通过应用程序引擎发出POST请求,从而触发413错误。我做错了什么?你不必通过应用程序引擎。您的前端(用户浏览器)请求一个已签名的URL,您的后端生成该URL并将其发送到前端。然后浏览器使用签名的URL将文件上载到云存储。您还可以想象,在上传结束时,如果您需要跟踪后端中的文件,从前端到后端的一个调用将提供上传的文件(名称和位置)。这很有意义。我将如何实现让浏览器请求已签名的URL以从访问我的应用程序的用户上传文件?用户选择要上载的文件并通过应用程序单击“提交”是否会触发此事件?实现这一点的代码需要在“home.html”中还是在“app.py”中?我用新代码更新了我上面的问题,我使用新代码通过app Engine部署应用程序,这样你就可以看到我在哪里/我做错了什么。非常感谢您在这方面的帮助,我想我很快就能弄明白。不,您的代码需要将文件发送到App Engine。签名的url在这里是无用的。浏览器需要直接将文件发送到存储器,而无需应用程序引擎中介。我会试着做一些原型来展示给你们看,但我在frontend/javascript方面非常糟糕!您好,谢谢您的帮助,但我不熟悉异步函数。在得到一个“未等待”的错误后,我做了一些研究。我当时无法安装axios,目前仍在排除故障。与此同时,我能够通过一个简单的requests.put来使用url,类似于axios.put方法,但是我仍然通过Google应用程序引擎得到413错误。

<Error>
<Code>MalformedSecurityHeader</Code>
<Message>Your request has a malformed header.</Message>
<ParameterName>content-type</ParameterName>
<Details>Header was included in signedheaders, but not in the request.</Details>
</Error>


os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = '/path/to/file.json'

EXPIRATION = datetime.timedelta(minutes=15)
FILE_TYPE = 'text/csv'
BUCKET = 'my-bucket'

def upload_via_signed(bucket_name, blob_name, filename, expiration, file_type):
    bucket = storage.Client().get_bucket(bucket_name)

    blob = bucket.blob(blob_name)

    signed_url = blob.generate_signed_url(method='PUT', expiration=expiration, content_type=file_type)

    requests.put(signed_url, open(filename.filename, 'rb'), headers={'Content-Type': file_type})

app = Flask(__name__)

app.config['UPLOAD_FOLDER'] = '/tmp'

@app.route('/')
def homepage():
    return render_template('home.html')

@app.route('/', methods = ['GET', 'POST'])
def upload_file():
    if request.method == 'POST':

        diag = request.files['file']
        filename_1 = secure_filename(diag.filename)
        filepath_1 = os.path.join(app.config['UPLOAD_FOLDER'], filename_1)
        diag.save(filepath_1)

        person = request.files['person']
        filename_2 = secure_filename(person.filename)
        filepath_2 = os.path.join(app.config['UPLOAD_FOLDER'], filename_2)
        person.save(filepath_2)

        upload_via_signed(BUCKET, 'diag.csv', diag, EXPIRATION, FILE_TYPE)

        upload_via_signed(BUCKET, 'person.csv', person, EXPIRATION, FILE_TYPE)

        df_diag = pd.read_csv('gs://' + BUCKET + '/' + 'diag.csv')
        print(df_diag.shape)
        return "done"

await axios.put(url, file);