첫 플라스크 애플리케이션을 작성하고 있습니다. 저는 파일 업로드를 다루고 있으며 기본적으로 업로드 된 파일의 데이터 / 내용을 저장하지 않고 읽고 결과 페이지에 인쇄하는 것입니다. 예, 사용자가 항상 텍스트 파일을 업로드한다고 가정합니다.
내가 사용하는 간단한 업로드 기능은 다음과 같습니다.
@app.route('/upload/', methods=['GET', 'POST'])
def upload():
if request.method == 'POST':
file = request.files['file']
if file:
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
a = 'file uploaded'
return render_template('upload.html', data = a)
지금은 파일을 저장하고 있지만 파일의 내용 / 데이터를 포함하는 ‘a’변수가 필요합니다. 어떤 아이디어가 있습니까?
답변
FileStorage
stream
필드를 포함 합니다. 이 개체는 IO 또는 파일 개체를 확장해야하므로 read
및 기타 유사한 메서드를 포함해야합니다 . FileStorage
또한 stream
필드 개체 속성을 확장 하므로 file.read()
대신 사용할 수 있습니다 file.stream.read()
. 또한 매개 변수 save
와 함께 인수를 사용 하거나 다른 IO 또는 파일 개체를 사용하여 다른 IO 또는 파일 개체로 복사 할 수 있습니다.dst
StringIO
FileStorage.stream
문서 참조 : http://flask.pocoo.org/docs/api/#flask.Request.files 및 http://werkzeug.pocoo.org/docs/datastructures/#werkzeug.datastructures.FileStorage .
답변
표준 Flask 항목을 사용하려는 경우 업로드 된 파일 크기가> 500kb 인 경우 임시 파일 저장을 피할 수있는 방법이 없습니다. 500kb보다 작 으면 파일 내용을 메모리에 저장하는 “BytesIO”를 사용하고 500kb 이상이면 내용을 TemporaryFile ()에 저장합니다 ( werkzeug 문서에서 설명 ). 두 경우 모두 업로드 된 파일 전체가 수신 될 때까지 스크립트가 차단됩니다.
이 문제를 해결하는 가장 쉬운 방법은 다음과 같습니다.
1) 들어오는 데이터의 모든 처리를 수행하는 파일과 유사한 IO 클래스를 만듭니다.
2) 스크립트에서 Request 클래스를 자신의 것으로 재정의하십시오.
class MyRequest( Request ):
def _get_file_stream( self, total_content_length, content_type, filename=None, content_length=None ):
return MyAwesomeIO( filename, 'w' )
3) Flask의 request_class를 자신의 것으로 바꿉니다.
app.request_class = MyRequest
4) 가서 맥주 마시기 🙂
답변
나는 똑같은 일을하고 텍스트 파일 (실제로는 팬더 용 CSV)을 열려고했습니다. 복사본을 만들고 싶지 않고 열어보고 싶을뿐입니다. form-WTF에는 멋진 파일 브라우저가 있지만 파일을 열고 임시 파일을 만들어 메모리 스트림으로 표시합니다. 후드 아래에서 약간의 작업으로
form = UploadForm()
if form.validate_on_submit():
filename = secure_filename(form.fileContents.data.filename)
filestream = form.fileContents.data
filestream.seek(0)
ef = pd.read_csv( filestream )
sr = pd.DataFrame(ef)
return render_template('dataframe.html',tables=[sr.to_html(justify='center, classes='table table-bordered table-hover')],titles = [filename], form=form)
답변
내 솔루션을 공유합니다 (모든 것이 플라스크의 Google 버킷에 연결되도록 이미 구성되었다고 가정).
from google.cloud import storage
@app.route('/upload/', methods=['POST'])
def upload():
if request.method == 'POST':
# FileStorage object wrapper
file = request.files["file"]
if file:
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = app.config['GOOGLE_APPLICATION_CREDENTIALS']
bucket_name = "bucket_name"
storage_client = storage.Client()
bucket = storage_client.bucket(bucket_name)
# Upload file to Google Bucket
blob = bucket.blob(file.filename)
blob.upload_from_string(file.read())
내 게시물
답변
메모리 파일을 디스크에 덤프하려는 경우. 이 코드를 사용할 수 있습니다.
if isinstanceof(obj,SpooledTemporaryFile):
obj.rollover()
답변
우리는 간단히 :
import io
from pathlib import Path
def test_my_upload(self, accept_json):
"""Test my uploads endpoint for POST."""
data = {
"filePath[]": "/tmp/bin",
"manifest[]": (io.StringIO(str(Path(__file__).parent /
"path_to_file/npmlist.json")).read(),
'npmlist.json'),
}
headers = {
'a': 'A',
'b': 'B'
}
res = self.client.post(api_route_for('/test'),
data=data,
content_type='multipart/form-data',
headers=headers,
)
assert res.status_code == 200
답변
기능상
def handleUpload():
if 'photo' in request.files:
photo = request.files['photo']
if photo.filename != '':
image = request.files['photo']
image_string = base64.b64encode(image.read())
image_string = image_string.decode('utf-8')
#use this to remove b'...' to get raw string
return render_template('handleUpload.html',filestring = image_string)
return render_template('upload.html')
html 파일에서
<html>
<head>
<title>Simple file upload using Python Flask</title>
</head>
<body>
{% if filestring %}
<h1>Raw image:</h1>
<h1>{{filestring}}</h1>
<img src="data:image/png;base64, {{filestring}}" alt="alternate" />.
{% else %}
<h1></h1>
{% endif %}
</body>