在android中将图像作为BLOB上传到SQL

Posted

技术标签:

【中文标题】在android中将图像作为BLOB上传到SQL【英文标题】:Uploading an image as BLOB to SQL in android 【发布时间】:2021-09-07 02:25:17 【问题描述】:

我正在制作一个 uni 项目,我选择制作一个也需要上传和检索图像的 android 应用。

我不明白的部分是上传和检索部分。

我尝试了很多事情,从尝试将位图转换为字节并以这种方式上传或创建路径但没有运气,无论我用多少谷歌搜索,我只能使用奇怪的 API 或一些 firebase 的东西获得结果。

我试过这个:https://www.maxester.com/blog/2019/10/04/upload-file-image-to-the-server-using-volley-in-android/

还有这个:https://www.youtube.com/watch?v=ULHyRwep3EU

还有其他一些不起作用的东西。

我有一个使用此代码的测试应用:

 public void openGallery()
        Intent intent = new Intent();
        intent.setType("image/*");
        intent.setAction(Intent.ACTION_GET_CONTENT);
        startActivityForResult(Intent.createChooser(intent, "Select Imgae"), PICK_IMAGE);
    
    public void onActivityResult(int requestCode, int resultCode, Intent data)
        super.onActivityResult(requestCode, resultCode, data);
        if(requestCode == PICK_IMAGE && resultCode == RESULT_OK && data != null)
            Uri pickedImage = data.getData();
            String[] filePath = MediaStore.Images.Media.DATA;
            Cursor cursor = getContentResolver().query(pickedImage, filePath, null, null, null);
            cursor.moveToFirst();
            String imagePath = cursor.getString(cursor.getColumnIndex(filePath[0]));
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inPreferredConfig = Bitmap.Config.ARGB_8888;
            Bitmap bmp = BitmapFactory.decodeFile(imagePath, options);
            ByteArrayOutputStream stream = new ByteArrayOutputStream();
            bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
            byte[] byteArray = stream.toByteArray();
            bmp.recycle();
            cursor.close();
            String url = "https://192.168.108.2/test/upload.php";
            StringRequest request = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() 
                @Override
                public void onResponse(String response) 
                    Toast.makeText(MainActivity.this, response.toString(), Toast.LENGTH_LONG);
                
            , new Response.ErrorListener() 
                @Override
                public void onErrorResponse(VolleyError error) 
                    Toast.makeText(MainActivity.this, error.getMessage().toString(), Toast.LENGTH_LONG);
                
            ) 
                protected Map<String, String> getParams()
                    Map<String, String> map = new HashMap<String, String>();
                    map.put("image", byteArray.toString());
                    return map;
                
            ;
        
    

而php是:

    $username = "root";
    $password = "";
    $dbname = "test";
    $servername = "localhost";
    
    $image = base64_decode($_POST['image']);
    
    $conn = new mysqli($servername, $username, $password, $dbname);
    $conn->set_charset("utf8");
    
    if ($conn->connect_error) 
        die("Connection failed: " . $conn->connect_error);
    
    $sql = "INSERT INTO image(img) VALUES('".$image."');";
    
    if($conn->query($sql))
        echo "Success";
    
    else
        echo "Failed";
    
?>

我还有一个图像字段类型为 MEDIUMBLOB 的数据库,大小为 5mil。

这显然不起作用(选择图像时应用程序崩溃)。 我希望有人指导我如何通过 android 将图像上传到 sql 以及如何检索它们,因为 google 一点帮助都没有。

小更新:

所以我环顾四周,我已经到了某个地方,但仍然没有上传图片。 我现在在 Android 中有这段代码:

public class MainActivity extends AppCompatActivity 
    Button uploadBtn, retrieveBtn;
    ImageView image;
    private static final int PICK_IMAGE = 1;
    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        image = findViewById(R.id.image);
        uploadBtn = findViewById(R.id.uploadBtn);
        retrieveBtn = findViewById(R.id.retrieveBtn);
        uploadBtn.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View v) 
                openGallery();
            
        );
        retrieveBtn.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View v) 
                getImage();
            
        );
    
    public void getImage()

    
    public void openGallery()
        Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
        photoPickerIntent.setType("image/*");
        startActivityForResult(photoPickerIntent, PICK_IMAGE);
    
    protected void onActivityResult(int reqCode, int resultCode, Intent data) 
        super.onActivityResult(reqCode, resultCode, data);


        if (resultCode == RESULT_OK) 
            try 
                final Uri imageUri = data.getData();
                final InputStream imageStream = getContentResolver().openInputStream(imageUri);
                final Bitmap bmp = BitmapFactory.decodeStream(imageStream);
                image.setImageBitmap(bmp);
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                bmp.compress(Bitmap.CompressFormat.JPEG, 100, baos);
                byte[] imageBytes = baos.toByteArray();
                String encodedImage = Base64.encodeToString(imageBytes, Base64.DEFAULT);
                //Toast.makeText(getApplicationContext(),"ByteArray created..",Toast.LENGTH_SHORT).show();
                String url = "http://192.168.108.2/test/upload.php";
                StringRequest request = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() 

                    @Override
                    public void onResponse(String response) 

                        Toast.makeText(getApplicationContext(), response.toString(), Toast.LENGTH_LONG);
                    

                , new Response.ErrorListener() 
                    @Override
                    public void onErrorResponse(VolleyError error) 
                        Toast.makeText(getApplicationContext(), error.getMessage().toString(), Toast.LENGTH_LONG);
                    
                )
                    protected Map<String, String> getParams()
                        Toast.makeText(getApplicationContext(), "I'm in stringrequest", Toast.LENGTH_LONG);
                        Map<String, String> map = new HashMap<String, String>();
                        map.put("image", encodedImage.toString());
                        return map;
                    
                ;
             catch (FileNotFoundException e) 
                e.printStackTrace();
                Toast.makeText(MainActivity.this, "Something went wrong", Toast.LENGTH_LONG).show();
            

        else 
            Toast.makeText(MainActivity.this, "You haven't picked Image",Toast.LENGTH_LONG).show();
        
    

还有这个 php 代码:

<?php
    $username = "root";
    $password = "";
    $dbname = "test";
    $servername = "localhost";
    $path = './images/';
    $uploadfile = $path . basename($_FILES['image']['name']);
    $echo "I'm in php";
    $conn = new mysqli($servername, $username, $password, $dbname);
    $conn->set_charset("utf8");
    if ($conn->connect_error) 
        die("Connection failed: " . $conn->connect_error);
    
    
    if(file_exists($path))
        if(move_uploaded_file($_FILES['image']['name'], $uploadfile))
            $sql = "INSERT INTO image(img) VALUES('".$uploadfile."');";
            echo "Success!";
        
        else
            echo "Failed";
        
    
    else
        mkdir($path);
        if(move_uploaded_file($_FILES['image']['name'], $uploadfile))
            $sql = "INSERT INTO image(img) VALUES('".$uploadfile."');";
            echo "Success!";
        
        else
            echo "Failed";
        
    
    
?>

当我选择一个图像时,它会选择它并将其放入图像视图中,但它不会将任何内容上传到 SQL。 怎么了?

忘了说:SQL 表中的 'img' 字段是大小为 300 的 varchar

【问题讨论】:

警告:您对SQL Injections 持开放态度,应该使用参数化的prepared statements,而不是手动构建查询。它们由PDO 或MySQLi 提供。永远不要相信任何形式的输入!即使您的查询仅由受信任的用户执行,you are still in risk of corrupting your data。 Escaping is not enough! 【参考方案1】:

你应该使用编码而不是解码来存储到数据库,因为它还没有被编码成base64,你还没有这样做。

$image = base64_encode($_POST['image']);

【讨论】:

好吧,应用程序仍然崩溃,但是感谢您让我注意到这一点。有点想念那个:D

以上是关于在android中将图像作为BLOB上传到SQL的主要内容,如果未能解决你的问题,请参考以下文章

在 Android 中将图像上传到 Cloudinary 失败

如何在 JavaScript 中将 Blob 转换为文件

在android中将多个图像上传到服务器的最快方法

如何在本机反应中将图像读取为二进制/ blob

如何调整我的模型以将上传的图像存储到我的数据库作为图像的链接而不是显示为 blob?

如何以BLOB格式将图像上传到Firebase存储?