2017-06-19 15 views
0

現在、私はアンドロイドデバイス用のwebserviceに取り組んでいます。デバイスがjsonデータをサーバー(tomcat8のjava webapp)にアップロードすると、データがdb (mysql)。ファイル内のすべてのデータをロードせずにJSON編集

私の問題は、データにはイメージが含まれており、アップロードファイルあたり約100MBになる可能性があるということです。画像は、他の情報とは別にアップロードすることはできません。

私はすべてのデータを1つのjsonに入れてアップロードする必要があります。

いくつかのjsonライブラリで完全にロードせずにファイルに直接データを追加することなく、jsonファイルにアクセスできるかどうか疑問に思っていました。

public static String toJson(Person person) { 
     try { 
      JSONObject jsonObject = new JSONObject(); 
      jsonObject.put("name", person.getName()); 
      jsonObject.put("surename", person.getSurname()); 

      JSONObject jsonAdd = new JSONObject(); 
      jsonAdd.put("address", person.getAddress().getAddress()); 
      jsonAdd.put("city", person.getAddress().getCity()); 
      jsonAdd.put("state", person.getAddress().getState()); 

      jsonObject.put("address", jsonAdd); 

      JSONArray jsonArray = new JSONArray(); 

      for(Person.ImageData pn : person.getImageData()) { 
       JSONObject jsonPhone = new JSONObject(); 
       jsonPhone.put("id", pn.getId()); 
       jsonPhone.put("base64", pn.getBase64()); 
       jsonArray.put(jsonPhone); 
      } 

      jsonObject.put("imageData", jsonArray); 

      return jsonObject.toString(); 

     } catch (JSONException e) { 
      e.printStackTrace(); 
     } 

     return null; 
    } 

このような出力付き:すべてを持つ既存の人に

{ 
     "imageData": [ 
     { 
      "base64": "someimage", 
       "id": "11111" 
     } 
    ], 
     "address": { 
     "state": "somewhere", 
       "address": "somewhere, 000", 
       "city": "somewhere city" 
    }, 
     "surname": "sure", 
      "name": "last" 
    } 

public class Person { 

    private String name; 
    private String surname; 
    private Address address; 
    private List<ImageData> data; 

    public class Address { 
     private String address; 
     private String city; 
     private String state; 
    } 

    public class ImageData { 
     private String id; 
     private String base64; 
    } 
} 

人は、このように生成されます。このクラスは、与えられた

例1つのImagedataを追加したいImageDataと入力すると、出力は次のようになります。

{ 
     "imageData": [ 
     { 
      "base64": "someimage", 
       "id": "11111" 
     }, 
     { 
      "base64": "someimage", 
       "id": "2222" 
     } 
    ], 
     "address": { 
     "state": "somewhere", 
       "address": "somewhere, 000", 
       "city": "somewhere city" 
    }, 
     "surname": "sure", 
      "name": "last" 
    } 

すべてをロードせずにファイルを直接編集することはできますか? imagedataコンテナを検索しますが、コンテンツ(IDとbase64)をロードしないで、コンテナに追加の要素(ID、ベース64)を追加するだけですか?

答えて

0

jsonを編集しようとしているうちに、編集用に大きなファイルを作成するのではなく、別のアイデアがあります。

最初に画像なしでデータを保存し、写真の代わりに画像にファイルパスのみを入れます。

ウェブサービスにアップロードするためのJSONが必要なのは、正しい情報がすべて取得されたときに生成できるからです。

だから私はこの依存関係を使用して、ジャクソンライブラリを使用して新しいファイルに与えられたデータをストリーム大きなファイル作成のためのJSON Builderを準備します

dependencies { 
... 
    compile 'com.fasterxml.jackson.core:jackson-core:2.7.2' 
... 
} 

そして、このインポートを:

import com.fasterxml.jackson.core.JsonFactory; 
import com.fasterxml.jackson.core.JsonGenerator; 

メソッドbuildLargeJson(File[], Person)でまずpublic_storage/documentsに新しいファイルを作成し、新しいファイルのFileStreamを介してデータをストリーミングするJsonGeneratorを作成します。

public static void buildLargeJson(File[] files, Person p) { 
     JsonFactory factory = new JsonFactory(); 
     File dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS); 
     File file = new File(dir, "large.json"); 

     try { 
      if (!dir.exists()) 
       dir.mkdirs(); 

      if (!file.exists()) 
       file.createNewFile(); 

      JsonGenerator generator = factory.createGenerator(new FileWriter(file)); 
      generator.writeStartObject(); 
      generator.writeFieldName("name"); 
      generator.writeString(p.getName()); 
      generator.writeFieldName("surname"); 
      generator.writeString(p.getSurname()); 

      if (files != null && files.length > 0) { 
       generator.writeFieldName("imageData"); 
       generator.writeStartArray(); 
       int counter = 1; 
       for (File f : files) { 
        generator.writeStartObject(); 
        generator.writeFieldName("id"); 
        generator.writeNumber(counter++); 
        generator.writeFieldName("base64"); 
        byte[] b = byteArrayFromFile(f); 

        if (b != null) { 
         generator.writeBinary(b); 
        } else { 
         generator.writeString("image not found"); 
        } 

        b = null; 

        generator.writeEndObject(); 
       } 
       generator.writeEndArray(); 
      } 
      generator.writeEndObject(); 
      generator.close(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

質問のPersonクラスを使用して、情報に入れたすべての画像を追加します。ピクチャはもちろん、byteArrayFromFile(File)メソッドで生成されたイメージ自体のバイト配列を使ってBase64として保存されます。バイト配列は、メモリを節約するためにビットマップをロードせずにイメージのFileInputStreamを読み込むことによって作成されます。約25MBのサイズの画像であっても、アプリケーションは120MBのJSONファイルを生成するために40MB未満のRAMしか使用しませんでした.Byte64へのバイトの変換は、JsonGeneratorのJacksonライブラリのメソッドwriteBinary(byte[])によって行われます。AndroidのAPI 19と25の標準WXGAタブレットエミュレータとサムスンA3 2016(ヌガー7.0)でテストされて

private static byte[] byteArrayFromFile(File imageFile) { 
     FileInputStream fis = null; 
     byte[] buffer = new byte[8192]; 
     byte[] b = null; 
     int bytesRead; 

     ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
     try { 
      fis = new FileInputStream(imageFile); 
      while ((bytesRead = fis.read(buffer)) != -1) { 
       baos.write(buffer, 0, bytesRead); 
      } 

      b = baos.toByteArray(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } finally { 
      try { 
       baos.close(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     }  
     return b; 
    } 

関連する問題