tl;dr
--GCS peut spécifier le type de contenu
--Chrome essaie d'afficher text / plain
dans Shift-JIS
--text / plain; charset = utf-8
est gentil
Créez un objet dans Google Cloud Storage avec un script similaire au suivant. Il s'agit d'une version modifiée du code googleapis / python-storage Example Usage pour stocker des chaînes contenant du japonais. Je vais sauter la création du bucket et l'authentification car elles ne sont pas pertinentes ici.
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": "Japonais"}')
Après avoir exécuté le script, je voudrais vérifier avec le navigateur si l'objet a été créé.
L'objet semble avoir été créé avec succès. Jetons un coup d'œil au contenu.
Google Cloud Storage peut générer des liens temporaires et vous pouvez télécharger des objets en suivant le lien depuis votre navigateur.
Le contenu de l'objet a été déformé comme ceci. C'est le problème cette fois.
file.json
{"name": "譌 ・ 譛 ャ 隱."}
J'oublie souvent d'encoder et de décoder des chaînes. ʻUpload_from_string` reçoit le type str, mais vérifiez s'il n'était pas nécessaire de l'encoder en UTF-8 etc.
En regardant Code, ce que fait ʻupload_from_string` est simple.
Extrait
def upload_from_string(réduction):
data = _to_bytes(data, encoding="utf-8")
string_buffer = BytesIO(data)
self.upload_from_file(réduction)
D'après ce qui précède, l'encodage de la chaîne semble correct.
Au fait, lorsque je regardais les informations sur l'objet dans le navigateur, j'ai trouvé une partie qui m'intéressait.
type="text/plain"
Dans GCS, les métadonnées sont données à l'objet. Il semble que vous puissiez spécifier l'en-tête de réponse lorsque l'objet est appelé dans les métadonnées Content-Type. https://cloud.google.com/storage/docs/metadata#content-type
Par défaut, cela devrait être ʻapplication / octat-stream ou ʻapplication / x-www-form-urlencoded
, mais il semble que ce soit text / plain
. Est-ce la cause?
Puisque j'ai émis l'hypothèse que la cause des caractères déformés est Content-Type: text / plain
, je vais mettre en place un serveur à portée de main et vérifier l'affichage afin de le séparer de GCS.
Configurez un serveur qui renvoie simplement une chaîne avec Content-Type: text / plain
avec bouteille.
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)
Ouvrir dans le navigateur
Je l'ai reproduit.
Ensuite, ouvrez-le dans le navigateur avec ʻapplication / json`.
ʻApplication / json` s'affiche correctement.
D'après ce qui précède, il semble bon de penser que Content-Type: text / plain
est la cause de caractères déformés indépendamment de GCS.
La question demeure de savoir pourquoi «Content-Type», qui devrait être «application / octat-stream» ou «application / x-www-form-urlencoded» par défaut dans GCS, est maintenant «text / plain».
Il s'agit du Blob.upload_from_string du module google.cloud.storage
utilisé pour le téléchargement. # L1650-L1660) fait quelque chose de mal
Extrait
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,
):
Puisque l'argument par défaut de content_type est text / plain
, il est implémenté pour être Content-Type: text / plain
sauf indication contraire.
Dans le passé, il semble que le spectateur pouvait modifier le codage des caractères, mais maintenant, il semble que l'inférence automatique du navigateur uniquement.
> document.characterSet
"Shift_JIS"
J'essaye d'afficher avec Shift_JIS
Jusqu'à présent, nous avons constaté que les deux points suivants sont à l'origine de caractères déformés.
--L'en-tête de réponse lorsque GCS renvoie un objet est Content-Type: text / plain
Content-Type: text / plain
avec Shift_JIS est brouilléLes caractères sont déformés lorsqu'ils sont affichés avec un navigateur, mais ce n'est pas un problème lors du traitement avec un programme comme suit.
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())
Dans mon cas, l'objet enregistré est quand même lu par un programme, donc c'était en fait un problème lorsque je voulais voir le contenu facilement. Cela peut poser un problème si vous l'utilisez comme hébergement de fichiers statiques.
Lorsque vous utilisez upload_from_string, il est bon de spécifier Content-type.
Pour json, vous pouvez utiliser ʻapplication / json, et pour le texte, vous pouvez spécifier un jeu de caractères comme
text / plain; charset = utf-8`, et Chrome le lira avec utf-8.
Je n'ai pas fait attention car cela change rarement récemment. Il n'y a pas beaucoup de leçons apprises cette fois, alors soyez prudent lorsque vous utilisez Blob.upload_from_string.
Recommended Posts