Как использовать BLOB с JSON и PHP? - PullRequest
8 голосов
/ 31 января 2011

У меня есть удаленная база данных с MySQL, и я храню фотографии пользователей моего приложения в базе данных в виде строки базы данных с типом LONGTEXT.

Я преобразую фотографии в строку с Base64.

Я подключаюсь к своей удаленной базе данных с помощью JSON и PHP, потому что для этого мне нужно использовать Base64, потому что, как я знаю, JSON и PHP нужно отправлять строки с параметрами, а с Base64 я могу преобразовать фотографию в строку .

Работает нормально, но очень медленно. Когда я загружаю фотографию размером 100 КБ, это занимает много времени, но когда я загружаю фотографию объемом 5 КБ, это занимает всего две или три секунды.

Мой друг сказал мне использовать BLOB вместо Base64, но как мне использовать BLOB с JSON и подключением PHP к базе данных? Также мне нужно хранить изображения в строке таблицы USER. Это связано с тем, что пользователи не имеют прав на загрузку файлов на удаленный сервер, но могут загружать фотографии, загружая их в виде строки в строке таблицы USER.

спасибо

EDIT:

это код, в котором требуется время ожидания (оно ожидает в строке: while ((line = reader.readLine()) != null) {, оно ожидает reader.readLine())

этот код получает одного пользователя из удаленной базы данных, требуется много времени, чтобы показать пользователя в моем приложении

public Friend RetrieveOneUser(String email)
{

    Friend friend=null;

    String result = "";
    //the parameter data to send
    ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
    nameValuePairs.add(new BasicNameValuePair("email",email));

    //http post
    InputStream is=null;
    try{
            HttpClient httpclient = new DefaultHttpClient();
            HttpPost httppost = new HttpPost(this.BaseURL + this.GetOneUser_URL);
            httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
            HttpResponse response = httpclient.execute(httppost);
            HttpEntity entity = response.getEntity();
            is = entity.getContent();
    }catch(Exception e){
            Log.e("log_tag", "Error in http connection "+e.toString());
    }
    //convert response to string
    try{

            BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8);
            StringBuilder sb = new StringBuilder();
            String line = null;
            while ((line = reader.readLine()) != null) {
                    sb.append(line + "\n");
            }
            is.close();

            result=sb.toString();
    }catch(Exception e){
            Log.e("log_tag", "Error converting result "+e.toString());
    }

    //parse json data
    try{
            JSONArray jArray = new JSONArray(result);


            for(int i=0;i<jArray.length();i++)
            {
                    JSONObject json_data = jArray.getJSONObject(i);
                    friend=new Friend(json_data.getString("email"),json_data.getString("password"), json_data.getString("fullName"), json_data.getString("mobilePhone"), json_data.getString("mobileOperatingSystem"),"",json_data.getString("photo"));
            }
    }
    catch(JSONException e){
            Log.e("log_tag", "Error parsing data "+e.toString());
    }

    return friend;
}

Ответы [ 4 ]

8 голосов
/ 31 января 2011

Сегментируйте запрос на две части:

  • Сначала загрузите JSON со всем, кроме изображения, вместо этого верните ссылку на изображение в виде URL
  • Во-вторых загрузите изображение какдвоичный кусок, потенциально асинхронный в зависимости от приложения

Я предполагаю, что у вас есть что-то вроде http://example.com/userinfo/xxx в качестве конечной точки, которая возвращает JSON?Добавьте конечную точку, такую ​​как http://example.com/userinfo_image/xxx, чтобы вернуть только изображение, затем вы можете вернуть его в виде двоичного фрагмента вместо Base64, кодирующего его в JSON.

Это означает, что вы делаете два HTTP-запроса вместо одного, но в зависимости от приложения вы можете выполнять загрузку изображений асинхронно, и в этом случае вы обычно получаете большой выигрыш в воспринимаемом времени отклика приложения с точки зрения пользователей.

Для получения информации о отложенной загрузке изображений вфон см. пост в блоге разработчиков Android для образца:

http://android -developers.blogspot.com / 2010/07 / multithreading-for-performance.html

Если вы не можете лениво загрузить изображение, подумайте о том, чтобы выполнять параллельные запросы для изображения и JSON одновременно.Поскольку двоичная версия изображения занимает намного меньшую пропускную способность сети и намного меньше обработки, когда вы получаете данные на телефон, она все равно должна казаться намного более быстрой.

1 голос
/ 31 января 2011

Чтобы ответить на ваш вопрос: Нет, JSON не поддерживает двоичные данные, вы должны каким-то образом избежать их перед отправкой. Хранение его как BLOB в MySQL не решит основные проблемы с инфраструктурой, которые у вас есть.

Насколько я понимаю, у вас есть устройство Android, которое загружает изображение на сервер PHP, этот сервер PHP кодирует изображение в Base64, помещает его в строку JSON и затем отправляет его на удаленный сервер (насколько удаленный удаленный «один и тот же центр обработки данных» по всей стране «по всему миру» в космическом пространстве на орбите Луны) MySQL-сервер через своего рода HTTP-интерфейс, на котором MySQL-сервер хранит образ Base64 как LONGTEXT. Чтобы вернуть изображение, клиент Android отправляет запрос в PHP, PHP отправляет запрос на удаленный сервер MySQL, затем PHP должен декодировать изображение Base64 и отправить его вниз.

Это ужасно неэффективно, вы будете страдать от задержки на каждом этапе пути.

Редактировать: хорошо, похоже, это проблема на стороне клиента, а не на стороне сервера ...

Если это так, то я бы посоветовал проверить сообщения @ Загрузка изображений на сервер PHP с Android , поскольку они должны иметь более эффективные примеры.

1 голос
/ 31 января 2011

Почему бы не сбросить изображение в виде файла на сервер и не вернуть URL записанного файла в ваш json? Это действительно то, как вы должны делать то, что вы хотите делать, так как http - это протокол, который вы должны использовать для передачи изображений через Интернет.

Код, подобный этому, должен делать то, что вы хотите на сервере

    //code to get your row from database

    //Code that writes it to a file.
    $Data = $row['myblobfield'];

    $fp = fopen('myimgname.jpg', 'w');
    fwrite($fp, $Data);

    fclose($fp);    

При этом поля вашего двоичного или длинного текста будут записаны в виде файла на вашем сервере, который вы затем сможете загрузить из своего мобильного приложения. Затем вы можете удалить эти временные файлы через определенный промежуток времени.

Надеюсь, это полезно

0 голосов
/ 31 января 2011

Замедление происходит из-за того, что json / base64 кодирует 100K данных, или из-за попадания в базу данных?Вероятно, это из-за кодировки и размещения файлов в файловой системе (поскольку все в комментариях плачут), в небольшом масштабе, не будет иметь никакого значения.

Сделайте некоторые измерения наразличные части операции, и попытаться определить, почему это медленно.Я не знаю, как еще можно получить блоб изображения в строку, закодированную в json без base64, я полагаю, вы можете попытаться избежать всего, что может быть столь же медленным, и надеюсь, что парсер не захлебнется.

Вы используете функцию json_encode в php или строите строку вручную?Попробуйте построить его вручную.Кодируете ли вы base64 необработанные данные из базы данных, или они кодируются перед их сохранением, вам следует кодировать их перед сохранением, чтобы сэкономить время при выводе.

...