Python、requestsを使ったファイルアップロード

Twitterでシェア FaceBookでシェア はてなブックマークでシェア

Python - サードパーティ製ライブラリ
2018年12月3日5:31に更新(約10日前)
2018年11月21日4:25に作成(約22日前)

基本的な使い方

import requests

url = 'http://test.com/api/image/'
file = {'upload_file': open('test.png', 'rb')}
res = requests.post(url, files=file)

すごく簡単です。強いて注意点を挙げるならば、

  1. URLを間違えないこと
  2. 名前を間違えないこと(upload_fileの部分)
  3. requests.post()files引数を使うこと

でしょうか。

Djangoで受け取る

Djangoで受け取る場合のサンプルコードです。

models.pyに、ImageFieldを持つシンプルなモデルを定義しています。

from django.db import models


class Photo(models.Model):
    """写真"""
    file = models.ImageField('ファイル')

views.pyです。

from django.contrib.sites.shortcuts import get_current_site
from django.http import HttpResponse
from django.views.decorators.http import require_POST
from django.views.decorators.csrf import csrf_exempt
from .models import Photo


@require_POST
@csrf_exempt
def upload(request):
    """/upload で呼び出される。"""
    # アップロードされたファイルを保存する。
    upload_file = request.FILES['file']
    photo = Photo(file=upload_file)
    photo.save()

    # ファイルにアクセスするためのURLを作成する。
    current_site = get_current_site(request)
    domain = current_site.domain
    download_url = '{0}://{1}{2}'.format(
        request.scheme,
        domain,
        photo.file.url,
    )

    # URLを文字列として返す。
    return HttpResponse(download_url, content_type="text/plain")

@require_POSTは、POSTメソッドだけ受け付けるデコレータです。よく使うやつですね。

@csrf_exemptですが、通常POSTメソッドでは{% csrf_token %}で発行されるトークンも一緒に送信する必要があります。これはCSRFという攻撃を防ぐためのものですが、今回のようにちょっとしたAPIとして公開したい場合は邪魔になったり、対策が面倒なこともあります。そのような場合にこのデコレータをつけることで、トークンが不要になり簡単に利用できるようになります。

URLの作成処理ですが、これはイディオムとして覚える価値のある処理だと個人的には思います。サイト内のURLをフルパスで作成する場合は大体このような処理をすることになります。

    # ファイルにアクセスするためのURLを作成する。
    current_site = get_current_site(request)
    domain = current_site.domain
    download_url = '{0}://{1}{2}'.format(
        request.scheme,
        domain,
        photo.file.url,
    )

そして、requestsでのアップロードを行うスクリプトupload.pyです。最初に紹介した内容とほぼ同じです。こちらはコメントを見れば何となくわかると思います。

import requests

# Djangoのuploadビューが呼ばれるURL
url = 'http://127.0.0.1:8000/upload/'

# ビュー内でのrequest.FILES['file']の'file'に対応
file = {'file': open('sample.png', 'rb')}

# 送信する。
res = requests.post(url, files=file)

# res.textに、画像にアクセスするためのURLが入っています。
print(res.text)

ソースコードのダウンロード

Githubに、ソースコードを置きました。READMEのとおり、クローンして実行すると試せます。

Twitterでシェア FaceBookでシェア はてなブックマークでシェア

記事にコメントする