1. ホーム
  2. Web プログラミング
  3. AJAX関連

ajax post download flaskのファイルストリームと中国語のファイル名の問題

2022-01-15 01:32:44

ファイルをダウンロードするためのajaxポスト

バックエンドはファイルのストリームを返し、これをflaskの return send_file (ファイルパス) バイナリファイルのストリームを返し、ファイル関連情報(ファイル名など)をヘッダで渡す。

フロントエンドでは URL.createObjectURL() を作成する。  DOMString URL オブジェクトを作成し、a ノードを作成し、URL オブジェクトを a ノードの href プロパティに割り当て、最後に click() メソッドを呼び出して a ノードをクリックし、ブラウザのダウンロードボックスをポップアップさせます。

画像を表示する

上記と同じ方法で、aをimgに、hrefをsrcに変えて、つまり、対象のimgタグのsrcにURLオブジェクトを書き込むことができます。

もう一つの方法は、バックエンドで画像をbase64文字列に変換して返す方法で、srcの値は次のような形になります。 "data:image/svg+xml;base64,${base string}" . (ここでsvg+xmlは画像フォーマットがsvgであることを、pngならpngであることを意味します)

中国語ファイル名文字化け

httpヘッダーから直接中国語のファイル名を転送する、より簡単な方法は、バックエンドでURLのトランスコードを行い(ここではpythonのurllib.parse.quoteを使用)、フロントエンドでは、次のような方法を使用します。 decodeURI() をデコードします。

また、ヘッダーの Content-Disposition: attachment; filename*=UTF-8''xxxxx しかし、直接の urlcode よりも ...... の方が互換性があり、Content-Disposition を設定するのが面倒なので、フロントエンドから Content-Disposition また、{{code Content-Disposition /code /code}}からのフロントエンドは、filenameを取るのが面倒なので、長い文字列を取得して、filename=の後に情報を取り出す方法を探します。

コードは以下の通りです。

フラスコ

from urllib.parse import quote
@file.route('/download', methods=["POST"])
def download_file():
  filename='xx' #filename
  filepath='xx/xx' #filepath
  res = make_response(send_file(filepath))
  # A custom header for the front-end to get the name
  res.headers['filename'] = quote(filename.encode('utf-8'))
  return res
javascript - async asynchronous fetch as an example.

async function download() {
  const res = await fetch(`http://xxx/file/download`, {
  method: "POST",
  body: JSON.stringify({}), // the body contains the data to be sent
  headers: { "Content-Type": "application/json" }
  responseType: 'blob'
 })

 if (res.ok) {
  const blData = await res.blob() // get blob data
  const urlObjData = window.URL.createObjectURL(new Blob([blData])) //create url object
  
  //Get the file for transcoding
  const fileName = decodeURI(fileNameres.headers.get('filename'))
  
  //create a tag Click on the a tag for download purposes
  const link = document.createElement('a')
  link.href = urlObjData
  link.download = fileName // the name of the downloaded file
  document.body.appendChild(link)
  link.click()
  
  document.body.removeChild(link)
  window.URL.revokeObjectURL(urlObjData);
  
  //Show image
  //xxx.src=urlObjData
 }
}

ps: flask ダウンロードファイル --- ファイルストリーム

htmlを使用します。

ダウンロード<

パイ

@app.route('/downloadfile/', methods=['GET', 'POST'])
def downloadfile():
  if request.method == 'GET':
    fullfilename = request.args.get('filename')
    # fullfilename = '/root/allfile/123.txt'
    fullfilenamelist = fullfilename.split('/')
    filename = fullfilenamelist[-1]
    filepath = fullfilename.replace('/%s'%filename, '')
    # Normal download
    # response = make_response(send_from_directory(filepath, filename, as_attachment=True))
    # response.headers["Content-Disposition"] = "attachment; filename={}".format(filepath.encode().decode('latin-1'))
    #return send_from_directory(filepath, filename, as_attachment=True)
    #stream read
    def send_file():
      store_path = fullfilename
      with open(store_path, 'rb') as targetfile:
        while 1:
          data = targetfile.read(20 * 1024 * 1024) # read 20M at a time
          if not data:
            break
          yield data

    response = Response(send_file(), content_type='application/octet-stream')
    response.headers["Content-disposition"] = 'attachment; filename=%s' % filename # If you don't add this line of code, it causes the problem below
    return response

ファイル名、ファイル形式がない、この場合、F12を開いてresponse.headersを通常と比較して確認します。

概要

ajaxポストダウンロードフラスクファイルストリームと中国語ファイル名についてのこの記事はすべて、より関連するajaxポストダウンロードフラスクファイルストリームの内容は、BinaryDevelopの過去の記事を検索するか、次の関連記事を閲覧を続けてくださいあなたは将来的にBinaryDevelopをよりサポートすることを願っています!。