8

APIのJavaクライアントを介してCKAN/datahub.io上のデータセットへのファイルのアップロードをテストしています。

public String uploadFile()
        throws CKANException {

    String returned_json = this._connection.MultiPartPost("", "");

    System.out.println("r: " + returned_json);
    return returned_json;
}

   protected String MultiPartPost(String path, String data)
            throws CKANException {
        URL url = null;

        try {
            url = new URL(this.m_host + ":" + this.m_port + path);
        } catch (MalformedURLException mue) {
            System.err.println(mue);
            return null;
        }

        String body = "";

        HttpClient httpclient = new DefaultHttpClient();
        try {
            String fileName = "D:\\test.jpg";

            FileBody bin = new FileBody(new File(fileName),"image/jpeg");
            StringBody comment = new StringBody("Filename: " + fileName);

            MultipartEntity reqEntity = new MultipartEntity();
            reqEntity.addPart("bin", bin);
            reqEntity.addPart("comment", comment);
            HttpPost postRequest = new HttpPost("http://datahub.io/api/storage/auth/form/2013-01-24T130158/test.jpg");
            postRequest.setEntity(reqEntity);
            postRequest.setHeader("X-CKAN-API-Key", this._apikey);
            HttpResponse response = httpclient.execute(postRequest);
            int statusCode = response.getStatusLine().getStatusCode();
            System.out.println("status code: " + statusCode);

            BufferedReader br = new BufferedReader(
                    new InputStreamReader((response.getEntity().getContent())));

            String line;
            while ((line = br.readLine()) != null) {
                body += line;
            }
            System.out.println("body: " + body);
        } catch (IOException ioe) {
            System.out.println(ioe);
        } finally {
            httpclient.getConnectionManager().shutdown();
        }

        return body;
    }

POSTリクエストに対する2つの応答:

  • アップロードしようとしたjpegが2.83Mbの場合の413エラー(「リクエストエンティティが大きすぎます」)。ファイルを小さいサイズに縮小すると、これは消えます。ファイルサイズのアップロードに制限はありますか?

  • 500エラー(「内部サーバーエラー」)。これは私が立ち往生しているところです。datahub.ioのデータセットが「データストア対応」ではないという事実に関係している可能性がありますか?(データセット内のリソースファイルの横に無効な[データAPI]ボタンが表示され、ツールチップに「データストアが無効になっているため、このリソースではデータAPIを使用できません」と表示されます。

=>この500エラーの考えられる理由はありますか?もしそうなら、どうすればクライアント側からそれを有効にできますか?(Pythonコードへのポインターは便利です!)

どうも!
PS:テスト目的で使用しているデータセット:http://datahub.io/dataset/testapi

4

2 に答える 2

6

例外ログにアクセスできる人だけが、500が発生している理由を知ることができます。

ただし、リクエストがデータストアと一緒に書き込まれたPythonクライアントから取得するものと同じであることを確認します:https ://github.com/okfn/ckanclient/blob/master/ckanclient/ init .py# L546

マルチパートリクエストで「bin」画像バッファと「comment」file_keyを送信しています。file_keyはアップロードごとに変更する必要があることに注意してください。そのため、タイムスタンプなどを追加してください。Content-Type:そして多分あなたはバイナリのためにを追加する必要があります。

于 2013-01-31T16:59:38.457 に答える
2

私はこの質問のポスターと同じような問題を経験してきました。かなりの試行錯誤の末、私は問題の解決策を思いつきました。私の場合、アップロードしたいCKANリポジトリをある程度制御できました。そうしないと、問題を解決できない可能性があります...

1.8バージョンのCKANを使用していると思いますか?

まず、CKANリポジトリがファイルのアップロードを許可するように設定されているかどうかを確認し、設定されていない場合は、それを許可するように構成します。これは、次の手順を使用してサーバーで実行できます:http ://docs.ckan.org/en/ckan-1.8/filestore.html#local-file-storage

あなたが言及した413エラーは次に対処されるべきです。これは、サーバーの一般的な構成と関係があります。私の場合、CKANはnginxを介してホストされていました。nginx.confファイルに「client_max_body_size100M」の行を追加しました。たとえば、この投稿を参照してください:http: //recursive-design.com/blog/2009/11/18/nginx-error-413-request-entity-too-large/

その後、500エラーだけが残ります。この記事を書いている時点では、CKANのAPIドキュメントはまだ少し未成熟です...実際、ファイルのアップロードに対して行ったようにリクエストを作成する必要があると言っています。ただし、このリクエストは、ファイルのアップロードの許可を求めるためのものです。クレデンシャルがファイルのアップロードをチェックアウトする場合(すべてのユーザーがファイルのアップロードを許可されているわけではありません)、応答にはファイルの送信先を示すオブジェクトが含まれます... APIが不明確なため、これら2つのリクエストをマージすることになりました。

次のシナリオは、ファイルのアップロードを処理するための2つのリクエストのフォローアップを示しています。リポジトリの設定が少し異なるため、シナリオの一部の手順が異なる場合に機能する可能性があります。エラーメッセージが表示された場合は、必ず応答の本文に手がかりがないか確認してください。

これが私が使用した認証要求です:

String body = "";
String generatedFilename=null;

HttpClient httpclient = new DefaultHttpClient();

try {

    // create new identifier for every file, use time
    SimpleDateFormat dateFormatGmt = new SimpleDateFormat("yyyyMMMddHHmmss");
    dateFormatGmt.setTimeZone(TimeZone.getTimeZone("GMT"));
    String date=dateFormatGmt.format(new Date());
    generatedFilename=date +"/"+filename;

    HttpGet getRequest = new HttpGet(this.CKANrepos+ "/api/storage/auth/form/"+generatedFilename);
    getRequest.setHeader(CKANapiHeader, this.CKANapi);

    HttpResponse response = httpclient.execute(getRequest);
    int statusCode = response.getStatusLine().getStatusCode();
    BufferedReader br = new BufferedReader(
             new InputStreamReader((response.getEntity().getContent())));

    String line;
    while ((line = br.readLine()) != null) {
         body += line;
    }
    if(statusCode!=200){
         throw new IllegalStateException("File reservation failed, server responded with code: "+statusCode+
          "\n\nThe message was: "+body);

    }
}finally {
     httpclient.getConnectionManager().shutdown();
}

これで、すべてがうまくいけば、サーバーは実際のファイルアップロードを行うときに使用するパラメーターを保持するjsonオブジェクトで応答します。私の場合、オブジェクトは次のようになりました。

{file_key:"some-filename-to-use-when-uploading"}

ただし、jsonオブジェクトを確認してください。これは、より多くの、または異なるパラメーターを必要とするカスタムckanリポジトリーがある可能性があることを理解しているためです。

これらの応答は、実際のファイルアップロードで使用できます。

        File file = new File("/tmp/file.rdf");
        String body = "";

        HttpClient httpclient = new DefaultHttpClient();

        try {

            FileBody bin = new FileBody(file,"application/rdf+xml");

            MultipartEntity reqEntity = new MultipartEntity();
            reqEntity.addPart("file", bin);

            reqEntity.addPart("key", new StringBody(filename));


            HttpPost postRequest = new HttpPost(this.CKANrepos+"/storage/upload_handle");
            postRequest.setEntity(reqEntity);
            postRequest.setHeader(CKANapiHeader, this.CKANapi);
            HttpResponse response = httpclient.execute(postRequest);
            int statusCode = response.getStatusLine().getStatusCode();
            BufferedReader br = new BufferedReader(
                    new InputStreamReader((response.getEntity().getContent())));

            String line;
            while ((line = br.readLine()) != null) {
                body += line;
            }
            if(statusCode!=200){
                getWindow().showNotification("Upload Statuscode: "+statusCode,
                        body,
                        Window.Notification.TYPE_ERROR_MESSAGE);

            }
        }finally {
            httpclient.getConnectionManager().shutdown();
        }

ご覧のとおり、file_keyプロパティは単純な「key」プロパティに変換されています。どうしてか分かりません。

これにより、ファイルがアップロードされます。このアップロードリクエストへの応答には、ファイルがアップロードされた場所を示すjsonオブジェクトが含まれます。編集:実際、私のckanはファイルがアップロードされたことを通知するために単純なhtmlページで応答したようです...ファイルが正しくアップロードされたことを確認するためにページを解析する必要がありました:(

私の場合、ファイルは

this.CKANrepos +"/storage/f/"+location

ここで、locationは、認証フェーズで返されるファイル名です。

前のコードフラグメントでは:

//the location of your ckan repository, including /api and possibly version, e.g.
this.CKANrepos = "http://datahub.io/api/3/";
this.CKANapiHeader="X-CKAN-API-Key";
this.CKANapi = "your ckan api key here";
于 2013-02-24T19:47:40.870 に答える