この記事を三行にまとめると
URLでアクセスできるファイルをダウンロードURLでアクセスできないファイルをダウンロード
CSVを作成してファイルとしてダウンロード
さーて、今週のあかつきのお宿は……
・URLでアクセスできるファイルをダウンロード
・URLでアクセスできないファイルをダウンロード
・CSVを作成してファイルとしてダウンロード
の三本です。それじゃあさっそく行ってみましょう。さーいしょーはロック……ジャン、ケン、グーッ!!(CV:ゴンさん)
URLでアクセスできる場合は「requests.get()」を使います。phpの「file_get_contens()」やcurlなんかと同じような機能です。もちろん画像以外のファイルのダウンロードにも使えますし、APIの開発なんかでも重宝する機能です。requestsがサーバーにない場合はpipコマンドでインストールできます。
データを取得できたらあとはそれをHttpResponse()に突っ込んでやるだけです。
そういうファイルをダウンロードする時はどうするか。
URLにアクセスできないところにあるファイルのデータを取得する場合は「open()」というファイルを読み込む組み込み関数を使います。open()でファイルを開くことができたらあとはURLでアクセスできるファイルと流れは同じです。
open()以外にもストリームを扱うioモジュールのFileIO()を使っても同じことができます。ストリームってのは……何だ? まあデータの一種だと思っとけば良いでしょう。
やってることは同じですがioモジュールを使った場合は「readall()」という関数でストリームの全バイトを読み込んでHttpResponse()に渡す必要があります。
ここでもioモジュールが活躍します。サーバーにファイルを保存する場合はopen()関数を使えば良いと思うんですが、ファイルを残さずダウンロードだけ行う場合はこっちの方が良いでしょう。
Django……というかPythonにはcsvというCSVを扱うためのモジュールが存在するので、それを使ってデータの書き込みを行い、HttpResponse()でファイルのダウンロード処理を行なっています。
最後の「sio.getvalue().encode(‘cp932’)」ってやつは書き込んだ値の文字コードを変換する処理です。文字コードがUTF-8の場合、CSVファイルをExcelで開くと文字化けしてしまうことがあるのでSHIFT-JISに変換しておく必要があります。cp932というのはSHIFT-JISの一種なのですが、SHIFT-JISよりも扱える文字が多いです。
ちなみにCSVじゃなくてもioモジュールを使えば通常のテキストファイルなども作成してダウンロードすることが可能です。
ファイルの読み込み方、あるいは書き込み方に差があるだけで、HttpResponse()を使ってダウンロードを行う点はどれも同じです。なのでとりあえずこれだけやり方を覚えておけば他のパターンの場合もこの応用でいけると思います。
ところでダウンロードと言えば、最近5G回線に関する情報をちょくちょく目にすることがあります。噂じゃ映画一本分くらいの動画ファイルでも数秒でダウンロードできるらしいんですけど……たかが数MBのBM98の楽曲データをダウンロードするのに一晩かかってた頃を思うと、超スピードとかそんなチャチなレベルじゃねえな、これ。そのうちダウンロードしようと頭の中で思った時にはすでにダウンロードが終わってる時代が来るのか?
・URLでアクセスできるファイルをダウンロード
・URLでアクセスできないファイルをダウンロード
・CSVを作成してファイルとしてダウンロード
の三本です。それじゃあさっそく行ってみましょう。さーいしょーはロック……ジャン、ケン、グーッ!!(CV:ゴンさん)
URLでアクセスできるファイルをダウンロード
まずはURLでアクセスできるファイルのダウンロードです。ブログで表示している画像などがこれに該当しますね。たぶん一番簡単なパターンだと思います。#views.py
from django.views.generic import TemplateView
from django.http import HttpResponse
import requests
class download(TemplateView) :
def get(self, request, *args, **kwargs) :
image = requests.get('https://norm-nois.com/static/images/sample.jpg')
response = HttpResponse(image.content, content_type = 'image/jpeg')
response['Content-Disposition'] = 'attachment; filename=サンプル画像.jpg'
return response
URLでアクセスできる場合は「requests.get()」を使います。phpの「file_get_contens()」やcurlなんかと同じような機能です。もちろん画像以外のファイルのダウンロードにも使えますし、APIの開発なんかでも重宝する機能です。requestsがサーバーにない場合はpipコマンドでインストールできます。
$ pip install requests
データを取得できたらあとはそれをHttpResponse()に突っ込んでやるだけです。
URLでアクセスできないファイルをダウンロード
URLでアクセスできるってことは誰にでも見えちゃうという意味なので、セキュリティ的にはガバガバです。個人情報が書かれたファイルなどを置く時は基本的にURLでアクセスできない場所に置いておいた方が良いでしょう。そういうファイルをダウンロードする時はどうするか。
#views.py
from django.views.generic import TemplateView
from django.http import HttpResponse
class download(TemplateView) :
def get(self, request, *args, **kwargs) :
file = open('/var/images/sample.jpg', 'rb')
response = HttpResponse(file, content_type = 'image/jpeg')
response['Content-Disposition'] = 'attachment; filename=サンプル画像.jpg'
return response
URLにアクセスできないところにあるファイルのデータを取得する場合は「open()」というファイルを読み込む組み込み関数を使います。open()でファイルを開くことができたらあとはURLでアクセスできるファイルと流れは同じです。
open()以外にもストリームを扱うioモジュールのFileIO()を使っても同じことができます。ストリームってのは……何だ? まあデータの一種だと思っとけば良いでしょう。
#views.py
from django.views.generic import TemplateView
from django.http import HttpResponse
import io
class download(TemplateView) :
def get(self, request, *args, **kwargs) :
file = io.FileIO('/var/images/sample.jpg')
response = HttpResponse(file.readall(), content_type = 'image/jpeg')
response['Content-Disposition'] = 'attachment; filename=サンプル画像.jpg'
return response
やってることは同じですがioモジュールを使った場合は「readall()」という関数でストリームの全バイトを読み込んでHttpResponse()に渡す必要があります。
CSVを作成してファイルとしてダウンロード
最後はサーバー上にファイルがない状態でデータをCSVファイルに落とし込んでダウンロードしてみたいと思います。#views.py
from django.views.generic import TemplateView
from django.http import HttpResponse
import io, csv
class download(TemplateView) :
def get(self, request, *args, **kwargs) :
sio = io.StringIO()
writer = csv.writer(sio)
writer.writerow(['A1', 'B1', 'C1'])
writer.writerow(['A2', 'B2', 'C2'])
writer.writerow(['A3', 'B3', 'C3'])
response = HttpResponse(content_type = 'text/csv')
response['Content-Disposition'] = 'attachment; filename=リスト.csv'
response.write(sio.getvalue().encode('cp932'))
return response
ここでもioモジュールが活躍します。サーバーにファイルを保存する場合はopen()関数を使えば良いと思うんですが、ファイルを残さずダウンロードだけ行う場合はこっちの方が良いでしょう。
Django……というかPythonにはcsvというCSVを扱うためのモジュールが存在するので、それを使ってデータの書き込みを行い、HttpResponse()でファイルのダウンロード処理を行なっています。
最後の「sio.getvalue().encode(‘cp932’)」ってやつは書き込んだ値の文字コードを変換する処理です。文字コードがUTF-8の場合、CSVファイルをExcelで開くと文字化けしてしまうことがあるのでSHIFT-JISに変換しておく必要があります。cp932というのはSHIFT-JISの一種なのですが、SHIFT-JISよりも扱える文字が多いです。
ちなみにCSVじゃなくてもioモジュールを使えば通常のテキストファイルなども作成してダウンロードすることが可能です。
sio = io.StringIO()
sio.write('テキストアフィルです')
response = HttpResponse(sio.getvalue(), content_type = 'plain/text')
response['Content-Disposition'] = 'attachment; filename=sample.txt'
return response
ファイルの読み込み方、あるいは書き込み方に差があるだけで、HttpResponse()を使ってダウンロードを行う点はどれも同じです。なのでとりあえずこれだけやり方を覚えておけば他のパターンの場合もこの応用でいけると思います。
ところでダウンロードと言えば、最近5G回線に関する情報をちょくちょく目にすることがあります。噂じゃ映画一本分くらいの動画ファイルでも数秒でダウンロードできるらしいんですけど……たかが数MBのBM98の楽曲データをダウンロードするのに一晩かかってた頃を思うと、超スピードとかそんなチャチなレベルじゃねえな、これ。そのうちダウンロードしようと頭の中で思った時にはすでにダウンロードが終わってる時代が来るのか?