In GCS mit Python platzierte Zeichenketten werden beim Anzeigen mit einem Browser verstümmelt

tl;dr

--GCS kann den Inhaltstyp angeben --Chrome versucht, "Text / Plain" in Shift-JIS anzuzeigen --text / plain; charset = utf-8 ist nett

Phänomen

Erstellen Sie ein Objekt in Google Cloud Storage mit einem Skript, das dem folgenden ähnelt. Dies ist eine modifizierte Version des Codes googleapis / python-storage Example Usage zum Speichern von Zeichenfolgen, die Japanisch enthalten. Ich werde die Erstellung des Buckets und die Authentifizierung überspringen, da sie hier nicht relevant sind.

from google.cloud import storage
client = storage.Client()
bucket = client.get_bucket('bucket-id-here')
blob = bucket.get_blob('remote/path/to/file.json')
blob.upload_from_string('{"name": "japanisch"}')

Nach dem Ausführen des Skripts möchte ich mit dem Browser prüfen, ob das Objekt erstellt wurde. スクリーンショット 2020-04-25 1.05.50.png

Das Objekt scheint erfolgreich erstellt worden zu sein. Werfen wir einen Blick auf den Inhalt. スクリーンショット 2020-04-25 2.23.36.png

Google Cloud Storage verfügt über eine Funktion zum Generieren eines temporären Links. Sie können das Objekt herunterladen, indem Sie dem Link im Browser folgen.

スクリーンショット 2020-04-25 1.07.30.png

Der Inhalt des Objekts wurde so verstümmelt. Diesmal ist dies das Problem.

file.json


{"name": "譌 ・ 譛 ャ 隱."}

Umfrage

Kodierung vergessen Hypothese

Ich vergesse oft, Strings zu codieren und zu decodieren. Ich übergebe den str-Typ an "upload_from_string", aber ich werde prüfen, ob ich ihn nicht in UTF-8 usw. codieren musste.

Mit Blick auf den Code ist das, was upload_from_string tut, einfach.

Auszug


def upload_from_string(Kürzung):
    data = _to_bytes(data, encoding="utf-8")
    string_buffer = BytesIO(data)
    self.upload_from_file(Kürzung)
  1. Machen Sie die Daten zu einer UTF-8-Byte-Zeichenfolge
  2. Lassen Sie die vorherige Bytezeichenfolge wie eine Datei behandeln
  3. Rufen Sie upload_from_file auf

Von oben sieht die Codierung der Zeichenfolge gut aus.

Hypothese vom Inhaltstyp

Übrigens, als ich mir die Objektinformationen im Browser ansah, fand ich einen Teil, der mich interessierte.

スクリーンショット 2020-04-25 2.23.36.png

type="text/plain"

In GCS werden dem Objekt Metadaten zugewiesen. Es scheint, dass Sie den Antwortheader angeben können, wenn das Objekt in den Metadaten des Inhaltstyps aufgerufen wird. https://cloud.google.com/storage/docs/metadata#content-type

Standardmäßig sollte es "application / octat-stream" oder "application / x-www-form-urlencoded" sein, aber es scheint, dass dies "text / plain" ist. Ist das die Ursache?

Experiment

Da ich angenommen habe, dass die Ursache für die verstümmelten Zeichen "Content-Type: text / plain" ist, werde ich einen Server einrichten und die Anzeige überprüfen, um sie von GCS zu trennen. Richten Sie einen Server ein, der einfach eine Zeichenfolge mit dem Inhaltstyp: text / plain mit Flasche zurückgibt.

server.py


from bottle import Bottle, HTTPResponse
import os

app = Bottle()

@app.route('/')
def serve():
    r = HTTPResponse(status=200, body='Hoge')
    r.set_header('Content-Type', 'text/plain')
    return r

if __name__ == '__main__':
    port = os.environ['PORT'] if 'PORT' in os.environ else '3000'
    app.run(host='0.0.0.0', port=port)

Im Browser öffnen

スクリーンショット 2020-04-25 2.28.16.png

Ich habe es reproduziert.

Übrigens, öffne es im Browser mit application / json etc.

スクリーンショット 2020-04-25 2.34.56.png

Wenn es sich um application / json handelt, wird es korrekt angezeigt.

Aus dem oben Gesagten scheint es gut zu denken, dass "Content-Type: text / plain" die Ursache für verstümmelte Zeichen ist, unabhängig von GCS.

Warum Inhaltstyp: Text / Nur

Es bleibt die Frage, warum der "Inhaltstyp", der in GCS standardmäßig "application / octat-stream" oder "application / x-www-form-urlencoded" sein sollte, jetzt "text / plain" war. Dies ist der Blob.upload_from_string des Moduls "google.cloud.storage", das zum Hochladen verwendet wird. # L1650-L1660) macht etwas falsch

Auszug


    def upload_from_string(
        self,
        data,
        content_type="text/plain",
        client=None,
        predefined_acl=None,
        if_generation_match=None,
        if_generation_not_match=None,
        if_metageneration_match=None,
        if_metageneration_not_match=None,
    ):

Da das Standardargument von content_type "text / plain" ist, wird es als "Content-Type: text / plain" implementiert, sofern nicht anders angegeben.

Browserverhalten

In der Vergangenheit schien es, dass der Betrachter die Zeichenkodierung ändern konnte, aber jetzt scheint es, dass nur die automatische Inferenz des Browsers.

> document.characterSet
"Shift_JIS"

Ich versuche mit Shift_JIS anzuzeigen

Die Größe des Problems

Bis zu diesem Punkt haben wir festgestellt, dass die folgenden zwei Punkte die Ursachen für verstümmelte Zeichen sind.

Die Zeichen werden beim Anzeigen mit einem Browser verstümmelt, aber es gibt kein Problem bei der Verarbeitung mit einem Programm wie folgt.

from google.cloud import storage
client = storage.Client()
bucket = client.get_bucket('bucket-id-here')
blob = bucket.get_blob('remote/path/to/file.txt')
print(blob.download_as_string())

In meinem Fall wird das gespeicherte Objekt ohnehin von einem Programm gelesen, sodass es tatsächlich ein Problem war, wenn ich den Inhalt leicht sehen wollte. Es kann ein Problem sein, wenn Sie es als statisches Datei-Hosting verwenden.

Lösung

Bei Verwendung von upload_from_string empfiehlt es sich, den Inhaltstyp anzugeben. Für json können Sie application / json verwenden, und für Text können Sie einen Zeichensatz wie text / plain; charset = utf-8 angeben, und Chrome liest ihn mit utf-8.

Zusammenfassung

Ich war nicht vorsichtig, weil es sich in letzter Zeit selten ändert. Diesmal werden nicht viele Lektionen gelernt. Seien Sie also vorsichtig, wenn Sie Blob.upload_from_string verwenden.

Recommended Posts

In GCS mit Python platzierte Zeichenketten werden beim Anzeigen mit einem Browser verstümmelt
Zeichenkodierung beim Umgang mit Dateien in Python 3
[Anfänger] Extrahieren Sie Zeichenketten mit Python
Beim Schreiben eines Programms in Python
Spiralbuch in Python! Python mit einem Spiralbuch! (Kapitel 14 ~)
Vorsichtsmaßnahmen beim Beizen einer Funktion in Python
Ich habe mit Python einen Zeichenzähler erstellt
Zeigen Sie Python 3 im Browser mit MAMP an
Pyopengl im Browser anzeigen (Python + Aal)
Fehler beim Installieren eines Moduls mit Python pip
[Python] Holen Sie sich die Dateien mit Python in den Ordner
Lesen Sie eine Datei mit verstümmelten Linien in Python
Erstellen Sie eine virtuelle Umgebung mit conda in Python
Vorsichtsmaßnahmen beim Umgang mit Kontrollstrukturen in Python 2.6
Ein Memo beim Erstellen einer Python-Umgebung mit Miniconda
Arbeiten Sie in einer virtuellen Umgebung mit Python virtualenv.
Erstellen Sie eine neue Seite im Zusammenfluss mit Python
Was verwenden Sie beim Testen mit Python?
Überlegen Sie, wann Sie mit Python3 und Scala3 in 10 Jahren gute Arbeit leisten können.
Ein Hinweis beim Überprüfen, ob der angegebene Schlüssel im definierten Wörterbuch mit Python vorhanden ist
Ich blieb stecken, als ich versuchte, einen relativen Pfad mit relative_to () in Python anzugeben
[Python] Lassen Sie nur Elemente im Array, die mit einer bestimmten Zeichenfolge beginnen
So konvertieren / wiederherstellen Sie einen String mit [] in Python
Spielen mit der benutzerlokalen API für künstliche Intelligenz in Python
Erstellen Sie einen einfachen Slackbot mit einer interaktiven Schaltfläche in Python
[Python] So erweitern Sie Variablen in einer Zeichenfolge
Versuchen Sie, in Python nach einem Profil mit einer Million Zeichen zu suchen
Vorsichtsmaßnahmen beim Umgang mit ROS MultiArray in Python
Versuchen Sie, Python mit pybind11 in ein C ++ - Programm einzubetten
Mailbox-Auswahl beim Abrufen von Google Mail mit imaplib von Python
Probleme beim Erstellen eines CSV-JSON-Konvertierungstools mit Python
Ich möchte mit einem Roboter in Python arbeiten.
Der süchtig machende Punkt des "Bayes-Denkens in Python"
Verwenden Sie communic (), wenn Sie eine Ausgabe in einem Python-Unterprozess empfangen
Japanische Ausgabe beim Umgang mit Python im Visual Studio
Führen Sie eine Python-Datei mit relativem Import in PyCharm aus
Dinge, die Sie bei der Verarbeitung von Zeichenfolgen in Python2 beachten sollten
Dinge, die Sie bei der Verarbeitung von Zeichenfolgen in Python 3 beachten sollten
Für diejenigen, die in Schwierigkeiten sind, weil NFC beim Lesen von NFC mit Python endlos gelesen wird
Eine Geschichte, die verschwunden ist, als ich einen Pfad angegeben habe, der mit tilda (~) in Python Open beginnt
Maschinelles Lernen Eine Geschichte über Menschen, die mit GBDT in GBDT in Python nicht vertraut sind
Vergleichen Sie Zeichenfolgen in Python
Strings in Python umkehren
[Python3] Sei vorsichtig beim Strippen (Strip, Lstrip, Rstrip)
Versuchen Sie, Python in der mit pipenv erstellten Django-Umgebung auszuführen
Ich habe ein einfaches Tippspiel mit tkinter of Python gemacht
Zeichenfolgen ohne Zeilenumbrüche in Python anzeigen (persönliches Memo)
Ein Allzweckprogramm, das Linux-Befehlszeichenfolgen mit Python formatiert
[Python] So erstellen Sie eine Liste von Zeichenfolgen Zeichen für Zeichen
Veröffentlichung einer Bibliothek, die Zeichendaten in Python-Bildern verbirgt
[Kleine Geschichte] [Python] Ersetzen Sie Zeichenfolgen in einem zweidimensionalen Array durch Zahlen
Erstellen Sie ein untergeordnetes Konto für die Verbindung mit Stripe in Python
Erstellen wir ein Skript, das sich bei Ideone.com in Python registriert.
Verhalten beim Angeben einer Liste mit shell = True im Unterprozess
Ein Memo, wenn mit Python + OpenCV schnell ein Gesicht erkannt wird
[Python] Hinweise beim Versuch, Numpy mit Cython zu verwenden
Ein Hinweis beim Erstellen eines gerichteten Diagramms mit Graphviz in Python
Verhalten in jeder Sprache, wenn Collouts mit for wiederverwendet werden
Vorsichtsmaßnahmen bei der Verwendung von Python mit AtCoder
Dinge, die Sie bei der Verwendung von CGI mit Python beachten sollten.