图片(base64格式)上传不正确。

3

很不幸,当我试图从Android设备上传一些图片到数据库时,遇到了一些问题。

这些图片在一个文件夹中。此文件夹包含图片以及其他东西。我不知道这些图片的名称,我需要仅上传图片(jpg)。上传图片之前,我需要使用base64对其进行编码。

首先,我从文件夹中获取jpg文件。然后,我从图像名称中获取ID。之后我通过base64进行编码:

Button upload = (Button) findViewById(R.id.upload);
upload.setOnClickListener(new View.OnClickListener() {
    public void onClick(View arg0) {
        String path = Environment.getExternalStorageDirectory().getPath();
        File dir = new File(path);
        File[] files = dir.listFiles();

        for (int i = 0; i < files.length; ++i) {
            if (files[i].getName().endsWith(".jpg")) {
                pics = new File(String.valueOf(files[i]));
                id = String.valueOf(files[i]);
                String sub = id.substring(id.lastIndexOf("/") + 1);
                int index = sub.indexOf("_");
                String book;
                if (index >= 0) {
                    book = sub.substring(0, index);
                    ID = book;
                    Log.e("ID", ID);
                }
                Bitmap imagex = BitmapFactory.decodeFile(pics.getAbsolutePath());
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                imagex.compress(Bitmap.CompressFormat.JPEG, 70, baos);
                byte[] b = baos.toByteArray();
                Image = Base64.encodeToString(b, Base64.DEFAULT);

                try {
                    new HttpAsyncTask(ID,Image,Nummer).execute("https://....");
                } catch (Exception e) {
                    Log.e("InputStream", e.getMessage());
                }

                Log.e("PICS", id);
            }
        }
    }
});

public String POST(String url) {
    InputStream inputStream;
    try {

        HttpClient httpclient = classxy.getNewHttpClient();

        HttpPost httpPost = new HttpPost(url);
        String json = "";

        JSONObject jsonObject = new JSONObject();

        jsonObject.put("bookId", ID);
        jsonObject.put("imageString", Image);
        jsonObject.put("imageNumber", Nummer);

        json = jsonObject.toString();

        StringEntity se = new StringEntity(json);

        httpPost.setEntity(se);

        httpPost.setHeader("Apikey", data);
        httpPost.setHeader("Modul", "upload_image");

        HttpResponse httpResponse = httpclient.execute(httpPost);
        inputStream = httpResponse.getEntity().getContent();


        if (inputStream != null)
            result = classxy.convertInputStreamToString(inputStream);
        else
            result = "Fehler!";
    } catch (Exception e) {
        Log.e("InputStream", e.getLocalizedMessage());
    }
    int num = Integer.parseInt(Nummer);
    num++;
    Nummer = Integer.toString(num);
    return result;
}

public class HttpAsyncTask extends AsyncTask<String, Void, String> {
    private final Object ID, Image, Nummer;

    public HttpAsyncTask(Object ID, Object Image, Object Nummer) {
        this.ID = ID;
        this.Image = Image;
        this.Nummer = Nummer;
    }

    protected String doInBackground(String... urls) {
        return POST(urls[0]);
    }

    protected void onPostExecute(String result) {
        if (result.matches("(.*)false(.*)")) {
            Toast.makeText(getApplicationContext(), "....", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(getApplicationContext(), "...", Toast.LENGTH_SHORT).show();
        }
        Log.e("RESPONSE", result);
    }
}

它确实通过base64对图像进行编码,并上传其中的一些图像。不幸的是,它只上传第一张图像或多次上传同一张图像。它从未按正确顺序上传正确数量的图像。我已经困扰这个问题有一段时间了,但无法弄清楚我做错了什么。
你能告诉我我做错了什么吗?

1
我强烈建议您使用像okhttp这样的工具来执行HTTP请求。 https://github.com/square/okhttp/wiki/Recipes - Vannen
我同意Vannen的观点。除了整体表现不太好之外,HttpClient在新版Android中已经被弃用。 - Ilya Polenov
它应该如何工作:1.我从文件夹中读取第一张图片。2.从文件名获取ID 3.使用base64对图像进行编码4.将第一个(编码的)图像发送到服务器。5.接收服务器结果。然后继续处理下一张图片,以此类推... - Hans1984
2个回答

5

你的程序似乎完全不具备线程安全性。

在for循环的每次迭代中,你都更新了字段IDImageNummer。很可能在第一次POST运行之前,循环已经完成了。你的观察结果支持了这个假设:

不幸的是,它只上传第一张图片或者同一张图片多次。

你可以通过记录对这些字段的每次访问来观察到这一点。你会发现,它并不像你期望的那样交替出现。

因此,你应该完全不使用这些字段来实现所有内容。而是使用本地变量并传递它们。如果你想将其用于多个上传,那么使用Nummer字段可能会有用。但是直接使用一个int可能更好:

upload.setOnClickListener(new View.OnClickListener() {
    public void onClick(View arg0) {
        String ID = "", Image;
        int Nummer = 0;
        [...]

        for (int i = 0; i < files.length; ++i) {
            if (files[i].getName().endsWith(".jpg")) {
                [...]

                try {
                    new HttpAsyncTask(ID,Image,Integer.toString(Nummer++)).execute("https://....");
                } catch (Exception e) {
                    Log.e("InputStream", e.getMessage());
                }

                Log.e("PICS", id);
            }
        }
    }
});

public String POST(String url, String ID, String Image, String Nummer) {
    InputStream inputStream;
    try {
        [...]
    } catch (Exception e) {
        Log.e("InputStream", e.getLocalizedMessage());
    }
    //int num = Integer.parseInt(Nummer);
    //num++;
    //Nummer = Integer.toString(num);
    return result;
}

public class HttpAsyncTask extends AsyncTask<String, Void, String> {
    private final String ID, Image, Nummer;

    public HttpAsyncTask(String ID, String Image, String Nummer) {
        this.ID = ID;
        this.Image = Image;
        this.Nummer = Nummer;
    }

    protected String doInBackground(String... urls) {
        return POST(urls[0], ID, Image, Nummer);
    }

    protected void onPostExecute(String result) {
        [...]
    }
}

好的,现在几乎可以使用了,太棒了 :D 当我上传四张照片时,它会上传第 2-4 张图片。现在只是跳过第一张图片。但是我猜我会设法解决这个问题。万分感谢你,伙计!谢谢你的帮助,你做得很棒! - Hans1984
搞定了。由于某种奇怪的原因,API不接受“1”作为数字,并忽略了带有图像编号1的请求,所以我只需将起始计数设置为2即可。现在它完美地工作了。再次感谢! - Hans1984
我本以为它不会像0一样,但很高兴现在它能正常工作了。 - tynn

1
我建议不要直接从for循环中调用Asynctask,因为没有任何监视器可以设置选定的图像。请按照以下步骤进行:
1)在for循环中获取所有图像ID、名称和编号,并将其存储到ArrayList中。
2)检查ArrayList是否为空,如果不是,则获取第一个位置的ID、图像和编号。
调用new HttpAsyncTask(ID,Image,Integer.toString(Nummer ++)).execute(“https://....”);
3)在HttpAsyncTask的onPostExecute(String result)方法中,首先删除第一个位置的数据,然后创建。
for loop (i=0;i<ArrayList.Size();i++) {
    ID=ArrayList first position data ID
    Image=ArrayList first position data IMAGE
    number=ArrayList first position data number

Call new HttpAsyncTask(ID,Image,Integer.toString(Nummer++)).execute("https://....");

}

所以这里首先发送第一张图片,然后发送第二张,以此类推,直到您的列表不再为空,并且每次选择的图片都不同。

就是这样...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接