So simulieren Sie das Hochladen von Post-Object-Formularen in OSS in Java

** Alibaba Cloud Object Storage Service (OSS) ** speichert Objekte in Ressourcen, die als "Buckets" bezeichnet werden. Post Object verwendet ein HTML-Formular, um die Datei in den angegebenen Bucket hochzuladen.

Vorwort

Der Alibaba Cloud Object Storage Service (OSS) ist ein benutzerfreundlicher Dienst, mit dem Sie große Datenmengen in der Cloud speichern, sichern und archivieren können. OSS fungiert als verschlüsseltes zentrales Repository und bietet Ihnen sicheren Zugriff auf Dateien auf der ganzen Welt. Mit einer garantierten Verfügbarkeit von bis zu 99,9% ist es außerdem ideal für globale Teams und internationales Projektmanagement.

Der Alibaba Cloud Object Storage Service (OSS) speichert Objekte sicher in Ressourcen, die als "Buckets" bezeichnet werden. Mit OSS haben Sie vollen Zugriff auf die Buckets und können die Protokolle und Objekte in jedem Bucket anzeigen. Sie können eine unbegrenzte Anzahl von Objekten in Ihrem Bucket lesen, schreiben, löschen und speichern. Die hohe Leistung von OSS unterstützt mehrere Lese- / Schreibvorgänge gleichzeitig. Die Datenübertragung zum Bucket erfolgt über SSL und ist verschlüsselt.

Post Object verwendet HTML-Formulare anstelle von Put, um Dateien in den angegebenen Bucket hochzuladen. Auf diese Weise können Sie Dateien über Ihren Browser in Ihren Bucket hochladen. Der Wunsch, Post Object in Java zu implementieren, ergibt sich aus kurzen Erklärungen verschiedener Support-Mitarbeiter. Demnach haben Benutzer, die diese Funktion benötigen, verschiedene schwierige Probleme, wenn sie versuchen, die Funktion gemäß der offiziellen Dokumentation zu implementieren. Dies geschieht, weil es keine offizielle Code-Referenz gibt.

Ablauf

Werfen wir einen Blick auf die Schritte, die der Benutzer ausführen sollte.

Als nächstes werde ich die beiden oben genannten Aspekte erläutern.

Eine ausführliche Einführung in Multipart- / Formulardaten finden Sie unter RFC 2388. Hier sind einige Dinge zu beachten. Lassen Sie uns sie einzeln besprechen.

  1. Am ersten Punkt enthält die Anforderung "Multipart / Formulardaten" eine Reihe von Feldern. Jedes Feld hat einen Content-Disposition-Header vom Typ "Formulardaten". Dieser Header enthält auch den Parameter "Name" zur Beschreibung des Inhalts der Formularfelder. Daher haben alle Felder ein ähnliches Format wie das in der Dokumentation gezeigte Beispiel.

Content-Disposition: form-data; name=“your_key"

Hinweis: Sowohl ":" als auch ";" folgen dem Leerzeichen.

  1. Der zweite zu beachtende Punkt ist, dass Sie, wenn Sie eine Benutzerdatei in ein Formular hochladen müssen, möglicherweise den Dateinamen und andere Dateiattribute im Header für die Inhaltsdisposition benötigen. Darüber hinaus gibt es ein optionales Attribut "Inhaltstyp", mit dem der Inhaltstyp der Datei für einen beliebigen MIME-Typwert im Formularfeld angegeben werden kann. Daher werden in der Dokumentation folgende Beispiele für "Datei" -Formularfelder aufgeführt:
Content-Disposition: form-data; name="file"; filename="MyFilename.jpg "
Content-Type: image/jpeg

Hinweis: Das ";" vor dem "Dateinamen" hat noch ein Leerzeichen. Ebenso steht im ":" nach dem "Content-Type" ein nachgestelltes Leerzeichen.

  1. Der dritte Punkt besteht darin, die Daten durch einen Rand zu trennen. Verwenden wir einen komplexen Rand, um ihn vom Hauptinhalt zu unterscheiden. Dies kann auf ähnliche Weise wie der Inhalt von HTTP-Headern erreicht werden, wie in der Dokumentation beschrieben.

Content-Type: multipart/form-data; boundary=9431149156168

  1. Der vierte zu beachtende Punkt ist, dass die Struktur jedes Formularfelds festgelegt ist. Jedes Formularfeld beginnt standardmäßig mit der Grenze "-" +, gefolgt von einem Wagenrücklauf (/ r / n). Darauf folgt die Formularfeldbeschreibung (siehe Punkt 1) und dann / r / n. Wenn der zu übertragende Inhalt eine Datei ist, enthalten die Dateinameninformationen auch den Wagenrücklauf (/ r / n) gefolgt vom Dateiinhaltstyp (siehe Punkt 2). Zusätzlich gibt es einen weiteren Wagenrücklauf (/ r / n), um den eigentlichen Inhalt zu starten, der mit / r / n enden muss.

  2. Beachten Sie auch, dass das letzte Formularfeld mit "-" + Grenze + "-" endet.

  3. Zusätzlich ist die Markierung / r / n erforderlich, um den HTTP-Anforderungsheader von den Body-Informationen (an der Kreuzung des Headers und des ersten Formularfelds) zu unterscheiden. Dies ist im Grunde eine zusätzliche leere Zeile wie ein Dokument, die folgendermaßen aussieht:

Content-Type: multipart/form-data; boundary=9431149156168

--9431149156168
Content-Disposition: form-data; name="key"

Bisher haben wir eine allgemeine Beschreibung der Anforderungssyntax in der offiziellen OSS-Dokumentation und eine zugehörige Analyse im Vergleich zum RFC 2388-Standard bereitgestellt.

Hier werden wir uns mit einigen Einschränkungen befassen, die mit der Verarbeitung verbunden sind, die das OSS-System zum Analysieren von POST-Objektanforderungen ausführt.

Die allgemeine Vorgehensweise von OSS zum Parsen einer POST-Anforderung ist in der folgenden Abbildung als Referenz dargestellt.

image.png

Der Ablauf der Anforderungsverarbeitung wird in drei Kernschritten zusammengefasst.

  1. Analysieren Sie die Grenzen von HTTP-Anforderungsheadern, um die Grenzen von Feldern zu unterscheiden.
  2. Analysieren Sie den Inhalt verschiedener Felder, bis der Fluss das Formularfeld "Datei" erreicht.
  3. Analysieren Sie das Dateiformatfeld.

In der Dokumentation wird daher betont, dass das Feld "Datei" im "letzten Feld" platziert wird. Andernfalls haben die Formularfelder nach "Datei" möglicherweise keine Auswirkung. Durch Platzieren des erforderlichen Formularfelds "Schlüssel" nach "Datei" wird sichergestellt, dass das Ergebnis ein ungültiges Argument ist.

Als nächstes werde ich den Arbeitsablauf kurz erläutern, wie in der Abbildung gezeigt.

  1. Überprüfen Sie, ob POLICY, OSSACCESSKEYID und SIGNATURE vorhanden sind. Diese Prüfung ist obligatorisch. Wenn eines der drei Felder POLICY, OSSACCESSKEYID und SIGNATURE angezeigt wird, sind die beiden anderen Felder erforderlich.
  2. Existenz von Autorität. Überprüfen Sie die Gültigkeit der Post-Anfrage anhand der Informationen von POLICY, OSSACCESSKEYID und SIGNATURE.
  3. Überprüfung der Richtlinienregeln Überprüfen Sie, ob die Einstellungen in den verschiedenen Formularfeldern der Anforderung mit den Richtlinieneinstellungen übereinstimmen.
  4. Überprüfen Sie die Rechtmäßigkeit der Länge.

Dies soll die Länge des Optionsfelds aufgrund der begrenzten Gesamtlänge des Post-Anforderungshauptteils überprüfen. 5) Analysieren Sie ParseContentType mit ParseFile. Analysiert das Feld ContentType im Feld Datei. Dieses Feld ist nicht erforderlich.

Dies endet mit Java-Code (Maven-Projekt), der das Hochladen von Post-Objekten in OSS als Referenz und Verwendung für diejenigen implementiert, die mit OSS vertraut sind.

import javax.activation.MimetypesFileTypeMap;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * Created by yushuting on 16/4/17.
 */
public class OssPostObject {

    private String postFileName = "your_file";  
Make sure that the file exists at the path indicated in the run code. 
    private String ossEndpoint = "your_endpoint";  
For example: http://oss-cn-shanghai.aliyuncs.com
    private String ossAccessId = "your_accessid";  This is your access AK
    private String ossAccessKey = "your_accesskey";  This is your access AK
    private String objectName = "your_object_name";  This is the object name after you upload the file
    private String bucket = "your_bucket";  Make sure that the bucket you created previously has been created. 

    private void PostObject() throws Exception {

        String filepath=postFileName;
        String urlStr = ossEndpoint.replace("http://", "http://"+bucket+".");  This is the URL for the submitted form is the bucket domain name

        LinkedHashMap<String, String> textMap = new LinkedHashMap<String, String>();
        // key
        String objectName = this.objectName;
        textMap.put("key", objectName);
        // Content-Disposition
        textMap.put("Content-Disposition", "attachment;filename="+filepath);
        // OSSAccessKeyId
        textMap.put("OSSAccessKeyId", ossAccessId);
        // policy
        String policy = "{\"expiration\": \"2120-01-01T12:00:00.000Z\",\"conditions\": [[\"content-length-range\", 0, 104857600]]}";
        String encodePolicy = java.util.Base64.getEncoder().encodeToString(policy.getBytes());
        textMap.put("policy", encodePolicy);
        // Signature
        String signaturecom = com.aliyun.oss.common.auth.ServiceSignature.create().computeSignature(ossAccessKey, encodePolicy);
        textMap.put("Signature", signaturecom);

        Map<String, String> fileMap = new HashMap<String, String>();
        fileMap.put("file", filepath);

        String ret = formUpload(urlStr, textMap, fileMap);
        System.out.println("[" + bucket + "] post_object:" + objectName);
        System.out.println("post reponse:" + ret);
    }

    private static String formUpload(String urlStr, Map<String, String> textMap, Map<String, String> fileMap) throws Exception {
        String res = "";
        HttpURLConnection conn = null;
        String BOUNDARY = "9431149156168";
        try {
            URL url = new URL(urlStr);
            conn = (HttpURLConnection) url.openConnection();
            conn.setConnectTimeout(5000);
            conn.setReadTimeout(30000);
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setRequestMethod("POST");
            conn.setRequestProperty("User-Agent",
                    "Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.6)");
            conn.setRequestProperty("Content-Type",
                    "multipart/form-data; boundary=" + BOUNDARY);

            OutputStream out = new DataOutputStream(conn.getOutputStream());
            // text
            if (textMap != null) {
                StringBuffer strBuf = new StringBuffer();
                Iterator iter = textMap.entrySet().iterator();
                int i = 0;
                while (iter.hasNext()) {
                    Map.Entry entry = (Map.Entry) iter.next();
                    String inputName = (String) entry.getKey();
                    String inputValue = (String) entry.getValue();
                    if (inputValue == null) {
                        continue;
                    }
                    if (i == 0) {
                        strBuf.append("--").append(BOUNDARY).append(
                                "\r\n");
                        strBuf.append("Content-Disposition: form-data; name=\""
                                + inputName + "\"\r\n\r\n");
                        strBuf.append(inputValue);
                    } else {
                        strBuf.append("\r\n").append("--").append(BOUNDARY).append(
                                "\r\n");
                        strBuf.append("Content-Disposition: form-data; name=\""
                                + inputName + "\"\r\n\r\n");

                        strBuf.append(inputValue);
                    }

                    i++;
                }
                out.write(strBuf.toString().getBytes());
            }

            // file
            if (fileMap != null) {
                Iterator iter = fileMap.entrySet().iterator();
                while (iter.hasNext()) {
                    Map.Entry entry = (Map.Entry) iter.next();
                    String inputName = (String) entry.getKey();
                    String inputValue = (String) entry.getValue();
                    if (inputValue == null) {
                        continue;
                    }
                    File file = new File(inputValue);
                    String filename = file.getName();
                    String contentType = new MimetypesFileTypeMap().getContentType(file);
                    if (contentType == null || contentType.equals("")) {
                        contentType = "application/octet-stream";
                    }

                    StringBuffer strBuf = new StringBuffer();
                    strBuf.append("\r\n").append("--").append(BOUNDARY).append(
                            "\r\n");
                    strBuf.append("Content-Disposition: form-data; name=\""
                            + inputName + "\"; filename=\"" + filename
                            + "\"\r\n");
                    strBuf.append("Content-Type: " + contentType + "\r\n\r\n");

                    out.write(strBuf.toString().getBytes());

                    DataInputStream in = new DataInputStream(new FileInputStream(file));
                    int bytes = 0;
                    byte[] bufferOut = new byte[1024];
                    while ((bytes = in.read(bufferOut)) != -1) {
                        out.write(bufferOut, 0, bytes);
                    }
                    in.close();
                }
                StringBuffer strBuf = new StringBuffer();
                out.write(strBuf.toString().getBytes());
            }

            byte[] endData = ("\r\n--" + BOUNDARY + "--\r\n").getBytes();
            out.write(endData);
            out.flush();
            out.close();

            // Read the returned data
            StringBuffer strBuf = new StringBuffer();
            BufferedReader reader = new BufferedReader(new InputStreamReader(
                    conn.getInputStream()));
            String line = null;
            while ((line = reader.readLine()) != null) {
                strBuf.append(line).append("\n");
            }
            res = strBuf.toString();
            reader.close();
            reader = null;
        } catch (Exception e) {
            System.err.println("Error in sending a POST request:  " + urlStr);
            throw e;
        } finally {
            if (conn != null) {
                conn.disconnect();
                conn = null;
            }
        }
        return res;
    }

    public static void main(String[] args) throws Exception {
        OssPostObject ossPostObject = new OssPostObject();
        ossPostObject.PostObject();
    }

}

Bitte beachten Sie, dass Sie pom.xml Folgendes hinzufügen müssen.

<dependency>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-sdk-oss</artifactId>
    <version>2.2.1</version>
</dependency>

Fazit

Mit Post Object können Sie Dateien basierend auf Ihrem Browser in Ihren Bucket hochladen. Die Post-Object-Nachrichtentextcodierung verwendet mehrteilige / Formulardaten. Bei Post-Object-Operationen überträgt das Programm Parameter als Formularfelder im Nachrichtentext. Post Object verwendet AccessKeySecret, um die Signatur der Richtlinie zu berechnen. Das POST-Formularfeld ist eine Option zum Hochladen öffentlicher Lese- / Schreib-Buckets. Wir empfehlen jedoch, dieses Feld zu verwenden, um POST-Anforderungen zu begrenzen.

Recommended Posts

So simulieren Sie das Hochladen von Post-Object-Formularen in OSS in Java
So zeigen Sie eine Webseite in Java an
So erstellen Sie eine Java-Umgebung in nur 3 Sekunden
So erstellen Sie einen Daten-URI (base64) in Java
So konvertieren Sie A in a und a in A mit logischem Produkt und Summe in Java
So konvertieren Sie eine Datei in ein Byte-Array in Java
So erstellen Sie einen Java-Container
So benennen Sie Variablen in Java
So entwickeln und registrieren Sie eine Sota-App in Java
So erstellen Sie ein Java-Array
So verketten Sie Zeichenfolgen mit Java
So implementieren Sie einen Job, der die Java-API in JobScheduler verwendet
So erstellen Sie ein neues Gradle + Java + Jar-Projekt in Intellij 2016.03
So implementieren Sie die Datumsberechnung in Java
So implementieren Sie den Kalman-Filter mit Java
Mehrsprachige Unterstützung für Java Verwendung des Gebietsschemas
So fügen Sie ein Video in Rails ein
So führen Sie eine Basiskonvertierung in Java durch
Wie erstelle ich einen Discord Bot (Java)
So erzwingen Sie Codierungskonventionen in Java
Einbetten von Janus Graph in Java
So veröffentlichen Sie eine Bibliothek in jCenter
So testen Sie eine private Methode und verspotten sie teilweise in Java
[Persönliches Memo] Interaktion mit dem Zufallszahlengenerator in Java
So übergeben Sie einen Proxy, wenn Sie REST mit SSL in Java auslösen
So ermitteln Sie den absoluten Pfad eines in Java ausgeführten Verzeichnisses
[Java] [Für Anfänger] So fügen Sie Elemente direkt in ein zweidimensionales Array ein
Zwei Möglichkeiten, einen Thread in Java + @ zu starten
Code zum Escapezeichen von JSON-Zeichenfolgen in Java
Versuchen Sie, ein Bulletin Board in Java zu erstellen
So erhalten Sie eine Klasse von Element in Java
Ich wollte (a == 1 && a == 2 && a == 3) in Java wahr machen
So führen Sie eine djUnit-Aufgabe in Ant aus
So fügen Sie in Spring Boot einen Klassenpfad hinzu
So erstellen Sie ein Thema in Liferay 7 / DXP
So implementieren Sie eine ähnliche Funktion in Rails
So erstellen Sie einfach ein Pulldown mit Rails
So lösen Sie Ausdrucksprobleme in Java
Wie schreibe ich Java String # getBytes in Kotlin?
So generieren Sie automatisch einen Konstruktor in Eclipse
So komprimieren Sie eine JAVA-CSV-Datei und verwalten sie in einem Byte-Array
So speichern Sie gleichzeitig Daten in einem Modell, das einem verschachtelten Formular zugeordnet ist (Rails 6.0.0)
So löschen Sie alle Daten in einer bestimmten Tabelle
Aufrufen von Funktionen in großen Mengen mit Java Reflection
[Java] So lassen Sie den privaten Konstruktor in Lombok weg
So implementieren Sie eine nette Funktion in Ajax mit Rails
So springen Sie von Eclipse Java zu einer SQL-Datei
Wie kann ich IBM Mainframe-Dateien in Java eingeben / ausgeben?
java: Wie schreibe ich eine generische Typliste? [Hinweis]
[Java] Wie man aus Janken rauskommt (entspricht Paiza Rang A)
So erstellen Sie ein Spring Boot-Projekt in IntelliJ
[Java] So erhalten Sie eine Anfrage per HTTP-Kommunikation
Ich habe versucht, eine Anmeldefunktion mit Java zu erstellen
So zeigen Sie eine Browser-Vorschau mit VS-Code an
[So fügen Sie ein Video mit Rails in haml ein]
So schreiben Sie eine Datumsvergleichssuche in Rails