1. 程式人生 > >安卓Base64批量上傳至伺服器

安卓Base64批量上傳至伺服器

Step1:整體過程

/**
* 由於請求框架開始就是Xutils compile ‘org.xutils:xutils:3.3.36’ 不做更改
* 1.第三方的圖片選擇器(支援選擇多張圖片、預覽、刪除等)
* 2.onActivityResult 返回選擇圖片的陣列
* 3.注意:介面有2個 A介面:專門用於接受圖片base64碼 B介面用來上傳 標題、內容和拼接的url連結
* 4.
* ①:將選取的圖片路徑的轉化為base64字串 encode()方法
* ②:選取多張時採用計數疊加一張張的上傳 每上傳一張將地址進行拼接 StringBuffer()方法
* ③:當上傳圖片完成時A介面結束,在呼叫B介面 傳入對應的引數即可,圖片是多張之後的url連結,要去除第一個,號否則後臺解析失敗 substring()方法
*/

這裡寫圖片描述

上圖中一共上傳了9張圖片,藍色部分就是一至9張的疊加連結,一共花了9秒 當然這些圖片都是很小的,如果是高清圖 記著一定要壓縮 否則會非常慢,因為流程非常多,容易卡死

Step3:進入主題
build.gradle 引入這些

//recyclerview 展示圖片的
 compile 'com.android.support:recyclerview-v7:25.3.1'
 //請求網路框架xutils
    compile 'org.xutils:xutils:3.3.36'
    //載入圖片的glide
    compile 'com.github.bumptech.glide:glide:3.7.0'
//相簿選擇器 compile 'me.iwf.photopicker:PhotoPicker:[email protected]' //壓縮圖片的 compile 'com.zxy.android:tiny:0.0.6' //刪除圖片顯示的snackbar compile 'com.android.support:design:26.0.0-alpha1

Step4:AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.helloworld.base64demo"
xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" /> <application android:name=".AppContext" android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> <!-- photopicker圖片選取介面 --> <activity android:name="me.iwf.photopicker.PhotoPickerActivity" android:theme="@style/Theme.AppCompat.NoActionBar" /> <!-- photopicker選取圖片預覽刪除介面 --> <activity android:name="me.iwf.photopicker.PhotoPagerActivity" android:theme="@style/Theme.AppCompat.NoActionBar" /> </application> </manifest>

Step5:4個java類

1.AppContext
2.MainActivity
3.PhotoAdapter
4.RecyclerItemClickListener

1.

package com.helloworld.base64demo;

import android.app.Application;
import com.zxy.tiny.Tiny;
import org.xutils.x;



public class AppContext extends Application {


    public static AppContext mInstace;

    @Override
    public void onCreate() {
        super.onCreate();
        /**
         * 初始化第三方庫
         */
        x.Ext.init(this);
        mInstace = this;
        /**
         * 壓縮的
         */
        Tiny.getInstance().getApplication();
    }
}

2.

package com.helloworld.base64demo;

import android.app.ProgressDialog;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.OrientationHelper;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.util.Base64;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import com.zxy.tiny.Tiny;
import com.zxy.tiny.callback.BitmapCallback;
import org.json.JSONException;
import org.json.JSONObject;
import org.xutils.common.Callback;
import org.xutils.http.RequestParams;
import org.xutils.x;
import java.io.ByteArrayOutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import me.iwf.photopicker.PhotoPicker;
import me.iwf.photopicker.PhotoPreview;


public class MainActivity extends AppCompatActivity {


    private RecyclerView recyclerView;
    private PhotoAdapter photoAdapter;
    private ArrayList<String> selectedPhotos = new ArrayList<>();
    //原生進度框
    private ProgressDialog progressdialog;
    private static final String TAG = "ReleaseActivity";

    /**
     * 圖片路徑
     */
    private List<String> photos;

    //釋出標題、內容介面 (這裡的連結換上自己伺服器上的)
    private static final String URL = "http://110.110.110.10:8080/api/information/publicInformation";
    //上傳圖片的介面 專門接受base64嗎
    private static final String URLIMAGE = "http://110.110.110.10:8080/api/information/uploadImage";


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        recyclerView = (RecyclerView) this.findViewById(R.id.recyclerView);
        progressdialog = new ProgressDialog(this);
        progressdialog.setMessage("正在上傳,請稍後...");

        //釋出按鈕事件
        TextView release_submit = (TextView) this.findViewById(R.id.release_submit);
        release_submit.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //點選後顯示彈框
                progressdialog.show();

                UploadImageBase64();
                SimpleDateFormat formatter = new SimpleDateFormat("yyyy年MM月dd日    HH:mm:ss     ");
                Date curDate = new Date(System.currentTimeMillis());//獲取當前時間
                String str = formatter.format(curDate);
                Log.e(TAG, "UploadImageBase6開始時間: " + str);
            }
        });
        initview();
    }

    private void initview() {

        photoAdapter = new PhotoAdapter(this, selectedPhotos);
        recyclerView.setLayoutManager(new StaggeredGridLayoutManager(3, OrientationHelper.VERTICAL));
        recyclerView.setAdapter(photoAdapter);
        recyclerView.addOnItemTouchListener(new RecyclerItemClickListener(this, new RecyclerItemClickListener
                .OnItemClickListener() {
            @Override
            public void onItemClick(View view, int position) {
                if (photoAdapter.getItemViewType(position) == PhotoAdapter.TYPE_ADD) {
                    PhotoPicker.builder()
                            .setPhotoCount(9) //可選擇的圖片數
                            .setShowCamera(true)//是否開啟相機
                            .setPreviewEnabled(false)
                            .setSelected(selectedPhotos)//選擇過的圖片出來在進入,預設打上勾
                            .start(MainActivity.this);
                } else {
                    PhotoPreview.builder()
                            .setPhotos(selectedPhotos)
                            .setCurrentItem(position)
                            .start(MainActivity.this);
                }
            }
        }));
    }

    /**
     * 選擇了圖片
     */
    private String str;

    private void UploadImageBase64() {

        //當number大於或等於圖片組大小時結束,並return
        if (number >= photos.size()) {
            //代表圖片上傳完畢,開始釋出
            if (photos.size() > 1) {
                //圖片大於1張時去除第一個,
                str = String.valueOf(sb).substring(1, sb.length());
            } else {
                str = String.valueOf(sb);
            }
            //請求的連結、誰釋出的(一般為uid)、釋出的標題、釋出的內容、最後拼接的圖片連結
            testUploadFile(URL, "1", "123", "456", str);
            //列印 最後拼接的圖片連結
            Log.e(TAG, "UploadImageBase64圖片: " + str);
            return;
        }

        //隨便找的壓縮方法 可以自己寫在工具類裡 不建議用第三方的
        Tiny.BitmapCompressOptions options = new Tiny.BitmapCompressOptions();
        Tiny.getInstance().source(photos.get(number)).asBitmap().withOptions(options).compress(new BitmapCallback() {
            @Override
            public void callback(boolean isSuccess, Bitmap bitmap) {
                //A介面 請求專門上傳圖片的連結、每次轉換時的base64字串、
                // 這裡的2只是區別是頭像上傳還是朋友圈上傳  可去除該引數
                UploadFile(URLIMAGE, "1", encode(photos.get(number)), "2");
                //列印 每張圖片的base64碼
                Log.e(TAG, "callback: 壓縮方法" + encode(photos.get(number)));
            }
        });
    }


    /**
     * 方法1
     */
    private String encode(String path) {
        Bitmap bitmap = BitmapFactory.decodeFile(path);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
        byte[] bytes = baos.toByteArray();
        //這裡有4種模式 defalut 是不連續的 me後臺接不到
        //NO_WRAP 是連續的 還有2種在這就不做解釋了
        byte[] encode = Base64.encode(bytes, Base64.NO_WRAP);
        String encodeString = new String(encode);
        return encodeString;
    }

    //msg 請求的結果
    private String msg;

    /**
     * 圖片上傳
     */
    private void testUploadFile(String url, String userId, String title, String content, String icons) {

        //4個對應的引數  使用者id、標題、內容、拼接的圖片地址
        RequestParams params = new RequestParams(url);
        params.addBodyParameter("userId", userId);
        params.addBodyParameter("title", title);
        params.addBodyParameter("content", content);
        params.addBodyParameter("icons", icons);
        x.http().post(params, new Callback.CacheCallback<String>() {
            @Override
            public void onSuccess(String result) {
                try {
                    JSONObject object = new JSONObject(result);
                    //返回狀態
                    String status = object.optString("status");
                    //返回的訊息
                    msg = object.optString("msg");
                    //成功關閉進度框
                    progressdialog.dismiss();
                    //200  說明成功
                    if (status.equals("200")) {
                        Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();
                        //記錄從點選到結束的所花時間 (可刪除)
                        SimpleDateFormat formatter = new SimpleDateFormat("yyyy年MM月dd日    HH:mm:ss     ");
                        Date curDate = new Date(System.currentTimeMillis());//獲取當前時間
                        String str = formatter.format(curDate);
                        Log.e(TAG, "UploadImageBase6結束時間: " + str);
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void onError(Throwable ex, boolean isOnCallback) {
                Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();
                //失敗也要關閉對話方塊
                progressdialog.dismiss();
                Log.e(TAG, "onError: ");
            }

            @Override
            public void onCancelled(CancelledException cex) {
                Log.e(TAG, "onCancelled: ");
            }

            @Override
            public void onFinished() {
                Log.e(TAG, "onFinished456: " + msg);
            }

            @Override
            public boolean onCache(String result) {
                Log.e(TAG, "onCache: ");
                return false;
            }
        });
    }

    /**
     * 圖片上傳
     * 地址,圖片集、圖片名稱、type(預設為2)
     */
    private int number = 0;
    private String status, data;
    private StringBuffer sb = new StringBuffer();

    private void UploadFile(String url, String userId, String icon, String type) {
        //專門接收base64 的介面  使用者id、圖片、type與上面一致 只是為了區別(可刪除)
        RequestParams params = new RequestParams(url);
        params.addBodyParameter("userId", userId);
        params.addBodyParameter("icon", icon);
        params.addBodyParameter("type", type);
        x.http().post(params, new Callback.CacheCallback<String>() {
            @Override
            public void onSuccess(String result) {
                try {
                    JSONObject object = new JSONObject(result);
                    status = object.optString("status");
                    data = object.optString("data");
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void onError(Throwable ex, boolean isOnCallback) {
                Log.e(TAG, "onError: " + status);
            }

            @Override
            public void onCancelled(CancelledException cex) {
                Log.e(TAG, "onCancelled: ");
            }

            @Override
            public void onFinished() {
                //說明上傳成功
                if (status.equals("200")) {
                    //當圖片大於1張是,進行分隔
                    if (photos.size() > 1) {
                        sb.append("," + data);
                    } else {
                        //等於一張時不用
                        sb.append(data);
                    }
                    //每上傳完一張遞增加1
                    number++;
                    //在此調取上傳圖片介面
                    UploadImageBase64();
                }
                Log.e(TAG, "onFinished: " + photos.size() + "\n" + sb);
            }

            @Override
            public boolean onCache(String result) {
                Log.e(TAG, "onCache: ");
                return false;
            }
        });
    }


    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_OK && (requestCode == PhotoPicker.REQUEST_CODE ||
                requestCode == PhotoPreview.REQUEST_CODE)) {
            photos = null;
            if (data != null) {
                //獲取圖片的list
                photos = data.getStringArrayListExtra(PhotoPicker.KEY_SELECTED_PHOTOS);
            }
            //清除list
            selectedPhotos.clear();
            if (photos != null) {
                //新增至list中
                selectedPhotos.addAll(photos);
            }
            //重新整理介面卡
            photoAdapter.notifyDataSetChanged();
        }
    }
}

3.

package com.helloworld.base64demo;

import android.content.Context;
import android.net.Uri;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import com.bumptech.glide.Glide;
import java.io.File;
import java.util.ArrayList;
import me.iwf.photopicker.utils.AndroidLifecycleUtils;


public class PhotoAdapter extends RecyclerView.Adapter<PhotoAdapter.PhotoViewHolder> {

    private ArrayList<String> photoPaths = new ArrayList<String>();
    private LayoutInflater inflater;

    private Context mContext;

    public final static int TYPE_ADD = 1;
    public final static int TYPE_PHOTO = 2;

    final static int MAX = 9;

    public PhotoAdapter(Context mContext, ArrayList<String> photoPaths) {
        this.photoPaths = photoPaths;
        this.mContext = mContext;
        inflater = LayoutInflater.from(mContext);

    }

    @Override
    public PhotoViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = null;
        switch (viewType) {
            case TYPE_ADD:
                itemView = inflater.inflate(R.layout.item_add, parent, false);
                break;
            case TYPE_PHOTO:
                //包裡面的
                itemView = inflater.inflate(R.layout.__picker_item_photo, parent, false);
                break;
        }
        return new PhotoViewHolder(itemView);
    }


    @Override
    public void onBindViewHolder(final PhotoViewHolder holder, final int position) {

        if (getItemViewType(position) == TYPE_PHOTO) {
            Uri uri = Uri.fromFile(new File(photoPaths.get(position)));

            boolean canLoadImage = AndroidLifecycleUtils.canLoadImage(holder.ivPhoto.getContext());

            if (canLoadImage) {
                Glide.with(mContext)
                        .load(uri)
                        .centerCrop()
                        .thumbnail(0.1f)
                        .placeholder(R.drawable.__picker_ic_photo_black_48dp)
                        .error(R.drawable.__picker_ic_broken_image_black_48dp)
                        .into(holder.ivPhoto);
            }
        }
    }


    @Override
    public int getItemCount() {
        int count = photoPaths.size() + 1;
        if (count > MAX) {
            count = MAX;
        }
        return count;
    }

    @Override
    public int getItemViewType(int position) {
        return (position == photoPaths.size() && position != MAX) ? TYPE_ADD : TYPE_PHOTO;
    }

    public static class PhotoViewHolder extends RecyclerView.ViewHolder {
        private ImageView ivPhoto;
        private View vSelected;

        public PhotoViewHolder(View itemView) {
            super(itemView);
            ivPhoto = (ImageView) itemView.findViewById(R.id.iv_photo);
            vSelected = itemView.findViewById(R.id.v_selected);
            if (vSelected != null) vSelected.setVisibility(View.GONE);
        }
    }
}

4.

package com.helloworld.base64demo;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;

/**
 * 點選事件 刪除
 */

public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener {
    private OnItemClickListener mListener;

    public interface OnItemClickListener {
        void onItemClick(View view, int position);
    }

    GestureDetector mGestureDetector;

    public RecyclerItemClickListener(Context context, OnItemClickListener listener) {
        mListener = listener;
        mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
            @Override
            public boolean onSingleTapUp(MotionEvent e) {
                return true;
            }
        });
    }

    @Override
    public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) {
        View childView = view.findChildViewUnder(e.getX(), e.getY());
        if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) {
            mListener.onItemClick(childView, view.getChildLayoutPosition(childView));
            return true;
        }
        return false;
    }

    @Override public void onTouchEvent(RecyclerView rv, MotionEvent e) {
    }

    @Override public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
    }
}

step6: 2個佈局

1.activity_main.xml
2.item_add.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">


    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#fff"
        android:paddingBottom="12dp"
        android:paddingLeft="6dp"
        android:paddingRight="6dp"
        android:paddingTop="12dp"/>


    <TextView
        android:id="@+id/release_submit"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_marginBottom="70dp"
        android:layout_marginLeft="22dp"
        android:layout_marginRight="22dp"
        android:layout_marginTop="70dp"
        android:background="#666"
        android:gravity="center"
        android:text="釋出"
        android:textColor="#fff"/>

</LinearLayout>

2.

<?xml version="1.0" encoding="utf-8"?>

<me.iwf.photopicker.widget.SquareItemLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:background="@drawable/xinxi_tupian"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</me.iwf.photopicker.widget.SquareItemLayout>

Step7:結束

相關推薦

Base64批量伺服器

Step1:整體過程 /** * 由於請求框架開始就是Xutils compile ‘org.xutils:xutils:3.3.36’ 不做更改 * 1.第三方的圖片選擇器(支援選擇多張圖片、預覽、刪除等) * 2.onActivityR

端同時文字和圖片到伺服器伺服器接收並處理

(更簡單的方法,點選安卓端同時上傳圖片和文字,伺服器接收並處理(二)) 之前看了很多部落格,找到的無非就是要麼只上傳json,要麼只上傳圖片。碰了許多的壁,因此我這裡寫一下自己已經測試成功的程式碼。 Android端使用Post上傳圖片和json程式碼 注

app端檔案到springMVC伺服器端的問題

先上程式碼,上傳檔案的封裝工具類如下: import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; imp

PHP介面檔案到伺服器

<?php /** * Created by PhpStorm. * User: Adaministrator * Date: 2018/3/30 * Time: 21:24 */ //連結資料庫 $servername = "182.254.147.87";

nginx優化-利用nginx限制HTTP的請求方法--防止指令碼被伺服器執行該指令碼對系統的破壞

利用nginx限制HTTP的請求方法 $request_method --防止指令碼被上傳至伺服器執行該指令碼對系統的破壞 可以上傳檔案,但是不能讓指令碼檔案執行成功 例如:站點目錄下有一個/image目錄,這個目錄是使用者上傳的一些圖片,不能阻止使用者上傳圖片,但要阻止使用者用特殊的方法執行裡面的檔

java檔案伺服器與檔案的刪除

一、檔案上傳(到伺服器中)程式碼如下: /** * 上傳檔案 * @param file 檔案 * @param request HttpServletRequest * @return 返回檔案基本資訊 */

c#將本地檔案伺服器(內網)

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; u

laravel伺服器出現Whoops, looks like something went wrong.

轉載:https://blog.csdn.net/pt1742395895/article/details/79722861 1.在本地能夠很好執行的laravel,上傳至伺服器就出現了這個問題“Whoops, looks like something

如何使用html5 canvas畫布對本地視訊進行截圖並伺服器

前端程式碼: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8">

JAVA實現客戶端圖片伺服器(SSM)(不使用input 標籤使用,瀏覽器圖片直接伺服器

JAVA實現客戶端圖片上傳至伺服器(SSM)(不使用input 標籤使用,瀏覽器圖片直接上傳伺服器) 這是本人第一篇部落格 想著記錄一下平時學習的過程,也提供給和我一樣正在學習java的同學們!!(如果有不懂的同學歡迎留言 有時間一定回覆,寫的不好的地方請多包涵) * 開始: 首先要

HTML5 本地裁剪圖片並伺服器 canvas圖片 canvas圖片裁剪

很多情況下使用者上傳的圖片都需要經過裁剪,比如頭像啊什麼的。但以前實現這類需求都很複雜,往往需要先把圖片上傳到伺服器,然後返回給使用者,讓使用者確定裁剪座標,傳送給伺服器,伺服器裁剪完再返回給使用者,來回需要 5 步。步驟繁瑣不說,當很多使用者上傳圖片的時候也很影響伺服器

多選本地相簿中的圖片並展示(仿QQ空間動態傳送頁面)伺服器

最近公司專案需要從本地上傳圖片到伺服器,直接去找才發現安卓居然還有這麼坑的時候,呼叫原生的只能選擇一張圖片,而且還沒有任何的細節優化,觸控圖片就直接返回了。這肯定不行啊!於是就在網上找啊找。。。找啊找。。。有很多都寫得花裡胡哨的看不懂,而且介面的UI也是low的不行。。終於

iOS Crash閃退日誌獲取和伺服器

 如何獲取crash閃退日誌 -- 工具檢視         先看第一個問題如何檢視,我搜索的方法有以下幾個:         第一個方法:XCode  的選單Window->Organizer    選擇Devices  ->  選中的手機 -> 點選手機名稱左邊的箭頭 會等到如下

選擇圖片功能【支援多選拍照預覽等】

在網上找了很多第三方的相簿拍照框架,都不盡人意,最後終於找到了一個比較好的框架,並且整合到了自己的demo中,花了兩天的時間吧感覺挺值的。老規矩不說廢話,直接上程式碼。 感謝某開源庫的作者:Alum 思路 目錄 先看目錄,我儘可能的在自己力所能及的範圍

tp5伺服器中出現各類錯誤的解決方法

1.連線Mysql提示1045 access denied for user 'root'@'localhost' using password yes的解決方法檢查上傳至伺服器中的tp5中的database.php中的連線資料庫的密碼是否正確2.連線Mysql提示Can’t

HTML5 本地裁剪圖片並伺服器(老梗)

很多情況下使用者上傳的圖片都需要經過裁剪,比如頭像啊什麼的。但以前實現這類需求都很複雜,往往需要先把圖片上傳到伺服器,然後返回給使用者,讓使用者確定裁剪座標,傳送給伺服器,伺服器裁剪完再返回給使用者,來回需要 5 步。步驟繁瑣不說,當很多使用者上傳圖片的時候也很影響伺服器效

iOS Crash閃退日誌的捕獲和伺服器

今天我要講的是app的閃退資訊的捕獲,以及日誌上傳。 涉及的技術點 異常處理 捕獲方式 訊號量 閃退日誌上傳 在APP開發中,對於開發者或者使用者最不能接受的bug就是APP崩潰,所以對於APP閃退的問題追蹤非常重要,有利於儘快的修復這個問題。現在

iOS中(相簿)攝像頭獲取的圖片伺服器被自動旋轉了

今天寫專案的時候發現, 通過相機(相簿)獲取到的圖片顯示是正的,但是上傳至伺服器後下次從伺服器讀取就被莫名其妙的旋轉了,開始時候以為是伺服器的原因,最後原來是我的原因:如果把通過相機獲取到的圖片,直接進行操作, 比如裁剪, 縮放, 則會把原圖片向右旋轉90度。 上網查後

webapi批量照片到ftp服務器(base64

指定 rem pass adl ace bapi bsp 需求 所在 一段demo。做的時候根據自己的需求改造下 public HttpResponseMessage AddVisitNew(HttpRequestMessage request, CustomerVisi

Java Springboot結合FastDFS實現檔案以及根據圖片url將圖片圖片伺服器

上一篇文章我們已經講解了如何搭建FastDFS圖片伺服器,環境我們準備好了現在就讓我們開始與Java結合將他應用到實際的專案中吧。本篇文章我們將會展示上傳圖片到FastDFS圖片伺服器以及通過外網的圖片url將圖片上傳至我們自己的圖片伺服器中。 1.建立springbo