質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
Flask

FlaskはPython用のマイクロフレームワークであり、Werkzeug・Jinja 2・good intentionsをベースにしています。

openpyxl

openpyxlは、Excel2007以降のファイル(xlsx/xlsm/xltx/xltm)を読み書きするためのPythonライブラリです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

325閲覧

Flaskで作成したExcelファイルをクライアントにダウンロードしたときにファイルが破損していて開けない

violet

総合スコア2

Flask

FlaskはPython用のマイクロフレームワークであり、Werkzeug・Jinja 2・good intentionsをベースにしています。

openpyxl

openpyxlは、Excel2007以降のファイル(xlsx/xlsm/xltx/xltm)を読み書きするためのPythonライブラリです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2024/10/10 10:07

編集2024/10/10 13:49

現在、Flaskを使ったWebアプリを作成しています。

サーバーでExcelフィアルを作成してそのExcelファイルをクライアントにダウンロードして開きたいのですが、Excelファイルをダウンロードすると毎回Excelファイルが破損して開けません。
Excelファイルの作成はopenpyxlを使っています。

サーバーで作成されたExcelファイルをサーバーから直接WinSCP経由で取得すると問題なくファイルを開くことができます。

Excelファイルに挿入するデータが原因なのかと思いExcelファイルに何も書き込まない状態でExcelファイルを生成しクライアントにダウンロードするように変更し動作させました。しかし、ファイルが破損してひらけません。なので書き込むデータが原因ではないと思われます。

また、VSCodeの拡張機能を使ってVSCode内で破損していると表示がでてくるExcelファイルを開くとデータを挿入したExcelファイルでも正常に見ることができます。

以下が該当部分のソースコードになります

Python

1@app.route('/write_log',methods=["GET","POST"]) 2@login_required 3def write_log(): 4 5 ・・・データを取得する処理・・・ 6 7 # Excelファイルの作成 8 XLSX_MIMETYPE = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' 9 wb = openpyxl.Workbook() 10 worksheet = wb.active 11 worksheet.title = "ログの出力" 12 13 ・・・ 取得データの挿入・・・ 14 15 # 列幅自動調整 16 for col in worksheet.columns: 17 max_length = 0 18 column = col[0].column_letter 19 for cell in col: 20 if len(str(cell.value)) > max_length: 21 max_length = len(str(cell.value)) 22 23 adjusted_width = (max_length + 2) * 2.5 24 worksheet.column_dimensions[column].width = adjusted_width 25 # フィルターの調整 26 worksheet.auto_filter.ref = 'A1:F1' 27 # 書き込みファイル名とその設定 28 now = datetime.datetime.now() 29 d = now.strftime('%Y%m%d%H%M%S') 30 downloadFileName = f"{d}.xlsx" 31 # 出力先ストリームの設定 32 output = BytesIO() 33 # ワークブックをメモリ上に保存 34 wb.save(output) 35 wb.close() 36 output.seek(0) 37 38 # バイトでファイルをDLする 39 return send_file( 40 BytesIO(output.getvalue()), 41 download_name=downloadFileName, 42 as_attachment=True, 43 mimetype = XLSX_MIMETYPE)

〇動作環境
サーバー:さくらサーバー(CGIを使用)
Python:3.8.12
モジュール情報
a2wsgi 1.10.7
alembic 1.13.1
anyio 4.5.0
blinker 1.8.2
certifi 2021.10.8
cffi 1.15.0
chardet 4.0.0
click 8.1.7
cryptography 2.9.2
et-xmlfile 1.1.0
exceptiongroup 1.2.2
fail2ban 0.11.2
fastapi 0.115.0
Flask 3.0.3
Flask-Login 0.6.3
Flask-Migrate 4.0.7
Flask-SQLAlchemy 3.1.1
Flask-WTF 1.2.1
greenlet 3.0.3
idna 2.10
importlib_metadata 7.1.0
importlib_resources 6.4.0
itsdangerous 2.2.0
Jinja2 3.1.4
Mako 1.3.5
MarkupSafe 2.1.5
openpyxl 3.1.4
pip 24.2
pycparser 2.21
pydantic 1.10.18
pyinotify 0.9.6
PyMySQL 1.0.2
pyOpenSSL 20.0.1
PySocks 1.7.1
requests 2.25.1
setuptools 57.0.0
six 1.16.0
sniffio 1.3.1
SQLAlchemy 2.0.30
sqlite3 0.0.0
starlette 0.38.5
typing_extensions 4.12.2
urllib3 1.26.7
Werkzeug 3.0.3
wheel 0.43.0
WTForms 3.1.2
zipp 3.19.2

Excelに挿入するデータに関して公開できないものなので省略させていただきました。申し訳ございません。

こちらに質問を掲載することに慣れてなく拙い文章でうまく伝わっているか分かりませんがよろしくお願いいたします。

Excelではこういった画面が表示されて「はい」を押すとExcelでファイルは開かれずフリーズします。
イメージ説明

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

bsdfan

2024/10/10 11:56 編集

mime-type の文字列に typo があるようですが、それが原因だったりしませんか? それと、seek(0) するのは close() のあとの方がいいのではないでしょうか。
violet

2024/10/10 13:24

ご確認していただきありがとうございます。 bsdfan様のおっしゃる「mime-type の文字列に typo がある」とはどういった意味でしょうか。教えていただけると幸いです。 また、「seek(0) するのは close() のあとの方がいいのではないでしょうか。」に関してはコードを ーーーーーーーーーーーーーー wb.save(output) wb.close() output.seek(0) ーーーーーーーーーーーーーー に変えて動かしてみましたが、現状動作は変わっていません。 質問のコードは上記のように変更しました。 よろしくお願いいたします。
bsdfan

2024/10/10 13:29

typo とはタイプミスのことです。officedocument となるべきところの o が抜けています。
violet

2024/10/10 13:49

申し訳ございませんでした。 そちらは私がこちらのサイトに転記する際のミスタイプでした。 コードを修正しました。申し訳ございませんでした。 よろしくお願いいたします。
quickquip

2024/10/10 15:53

> サーバーでExcelフィアルを作成してそのExcelファイルをクライアントにダウンロードして開きたいのですが、Excelファイルをダウンロードすると毎回Excelファイルが破損して開けません。 > また、VSCodeの拡張機能を使ってVSCode内で破損していると表示がでてくるExcelファイルを開くと このあたりを見るといかにもサーバにファイルを作成しているように読めますが、"該当のソースコード"はこんな動作をしていませんよね。このコードはいったい何だと思って読んだらいいのでしょう?
quickquip

2024/10/10 15:57

あとダウンロードしたファイルはzipファイルの形式になっているのでしょうか? (xlsxはzipファイルです) 「zipだけど中が壊れている」のか「zipになってない」のか、後者なら実際中身はなんなのか、はバイナリエディタなどを使って見てみるべきだと思います。
violet

2024/10/10 23:57

確認していただきありがとうございます。 >サーバにファイルを作成しているように読めます 私の文書の書き方が悪かったです。申し訳ございません。 正確にはこのwebアプリの「~/write_log」パスにアクセスするとサーバー内に一時ファイルを作成して、その作成したファイルをクライアントにダウンロードするというプログラムと理解しております。 >ダウンロードしたファイルはzipファイルの形式になっているのでしょうか? (xlsxはzipファイルです) Excelのファイルがzipファイルなのはなんとなく知っているという程度で、正直そこまで詳しくは理解しておりません。 クライアントにダウンロードしたExcelファイルを以下のサイト https://www.arktran.com/BackNumber001.html の手順で「手動によるofficeファイルの更新手順」を行ったところ正常にExcelファイルを開くことが確認できました。 私の理解と知識不足と思っております。 よろしくお願いいたします。
violet

2024/10/11 00:20

Excelファイルをzipにして解凍したあとにその解凍したフォルダー内の「xl/workbook.xml」のシート名が文字化けしていたのを発見したので本日、Excelのシート名を全角文字を含めず ---------------------------------------------- # Excelファイルの作成 XLSX_MIMETYPE = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' wb = openpyxl.Workbook() worksheet = wb.active worksheet.title = "ログの出力"  ←この部分 ---------------------------------------------- の部分を ---------------------------------------------- # Excelファイルの作成 XLSX_MIMETYPE = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' wb = openpyxl.Workbook() worksheet = wb.active worksheet.title = "log"  ←この部分 ---------------------------------------------- に変更しました。 クライアントにダウンロードした後にクライアント側で開こうとするとファイルは破損しているとダイアログ表示されますが、修復をすると正常にファイルは表示されました。 よろしくお願いいたします。
bsdfan

2024/10/11 00:43 編集

> サーバー内に一時ファイルを作成して、その作成したファイルをクライアントにダウンロードする 質問に書かれているプログラムでは、一時ファイルは作成せず、(BytesIOを使って)メモリ上だけで完結しています。 > サーバーで作成されたExcelファイルをサーバーから直接WinSCP経由で取得すると問題なく これで取得したファイルはどれのことでしょうか、という質問がでてきます。 (一時ファイルを作成するようなプログラムに変更して試されたのかなと思っていたのですが、上記のようなコメントがでてくるということは違っているのでしょうか?) xlsx を作る部分に問題があるのか、Flaskでの転送に問題があるのか、切り分けれるようなことを試す必要があります。
violet

2024/10/11 01:27

ご確認ありがとうございます。 >サーバーで作成されたExcelファイルをサーバーから直接WinSCP経由で取得すると問題なく これで取得したファイルはどれのことでしょうか 私の説明不足でした。申し訳ございません。bsdfan様のおっしゃる通りで一時ファイルを作成するようなプログラムに変更して実施しました。 私の書き方が悪かったのが原因です。申し訳ございません。 以下に私の行った作業をまとめました。 (1)BytesIOを使ってメモリ上で完結したかったので質問に張り付けたコードを作成して動作させた →クライアントにExcelファイルをダウンロードし開いたところファイルが破損して開けなった (2)Excelファイルの生成に問題があるのかと思いBytesIOではなくサーバ内にExcelファイルを生成するようにプログラムを以下に変更 ーーーーーー変更前コードーーーーーーー # 書き込みファイル名とその設定 now = datetime.datetime.now() d = now.strftime('%Y%m%d%H%M%S') downloadFileName = f"{d}.xlsx" # 出力先ストリームの設定 output = BytesIO() # ワークブックをメモリ上に保存 wb.save(output) wb.close() output.seek(0) # バイトでファイルをDLする return send_file( BytesIO(output.getvalue()), download_name=downloadFileName, as_attachment=True, mimetype = XLSX_MIMETYPE) ーーーーーーーーーーーーーーーーーーー ーーーーーー変更後コードーーーーーーー # 書き込みファイル名とその設定 now = datetime.datetime.now() d = now.strftime('%Y%m%d%H%M%S') downloadFileName = f"{d}.xlsx" # ワークブックを保存 wb.save(downloadFileName) wb.close() # ファイルをDLする return send_file( downloadFileName, download_name=downloadFileName, as_attachment=True, mimetype = XLSX_MIMETYPE) ーーーーーーーーーーーーーーーーーーー →生成したExcelファイルをWinSCP経由で取得してファイルを開いたところ問題なく開けた (3)(2)の変更前コードにコードを戻してシート名を半角文字に変更 ---------------変更前------------------------- # Excelファイルの作成 XLSX_MIMETYPE = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' wb = openpyxl.Workbook() worksheet = wb.active worksheet.title = "ログの出力"  ←この部分 ---------------------------------------------- ----------------変更後------------------------ # Excelファイルの作成 XLSX_MIMETYPE = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' wb = openpyxl.Workbook() worksheet = wb.active worksheet.title = "log"  ←この部分 ---------------------------------------------- →クライアントにダウンロードした後にクライアント側で開こうとするとファイルは破損しているとダイアログ表示されますが、修復をすると正常にファイルは表示されました。 現状をまとめるとこのような感じです。 不慣れで拙い文章で申し訳ございません。よろしくお願いいたします。
guest

回答1

0

自己解決

Excelファイルをゼロから生成していいましたが、もともと何もデータを挿入していないブックをテンプレートとしてサーバー内に保存しておき、そのファイルにデータを挿入→メモリ上に保存という風にプログラムを変更したらExcelのファイルが破損することは無くなりました。
以下がコードです

Python

1・・・省略・・・ 2 3# Excelファイルの読み込み 4XLSX_MIMETYPE = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' 5wb=openpyxl.load_workbook('temp_log.xlsx') 6worksheet=wb.active 7 8・・・データの挿入・・・ 9 10# 出力先ストリームの設定 11output = BytesIO() 12# ワークブックをメモリ上に保存 13wb.save(output) 14output.seek(0) 15wb.close() 16 17# 書き込みファイル名とその設定 18now = datetime.datetime.now() 19d = now.strftime('%Y%m%d%H%M%S') 20downloadFileName = f"{current_user.class_name}_{d}.xlsx" 21 22return send_file( 23 BytesIO(output.getvalue()), 24 download_name=downloadFileName, 25 as_attachment=True, 26 mimetype = XLSX_MIMETYPE, 27 conditional=True 28 )

ご意見を下さったbsdfan様ありがとうございました。

投稿2024/10/12 00:07

violet

総合スコア2

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問