Java - SpringMVC 接受iOS客户端AFNetworking提交的图片到阿里云OSS

前言

客户端开发的时候必须会涉及到上传图等这样的操作

解决方案

1.需要申请一个阿里的OSS服务
2.在阿里的后台的OSS对象存储里面创建一个Bucket
3.配置AccessKey SecretKey等:创建ACCESSKEY
4.快速开发-参考SDK的使用文档:
里面包括 IOS-SDK的使用 java- SDK的使用
思路:一般的我们的上传方案是将图片上传到我们的服务器 然后再上传到阿里的OSS,更安全,而不是直接用IOS的SDK直接上传到OSS, 所以以iOS客户端为例子,我用AFNetworking,将图片Post到后台,我这里的后台是SpringMVC来接受前端的文件流

代码分析

前提条件:项目中要引入Jar依赖:

<dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.4</version>
        </dependency>
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.1</version>
        </dependency>

        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
            <version>1.9</version>
        </dependency>

Spring配置文件要配置:

<!-- 上传文件  依赖common -io等jar-->
    <bean id="multipartResolver"
        class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    </bean>
<!-- 上传文件 -->

这样项目就有接受文件流的能力的了

SpringMVC的Controller的代码:

@Controller
@RequestMapping(value = "/common", method = { RequestMethod.POST })
public class CommonController {

    @Autowired
    public UploadService service;

       //上传图片
       @RequestMapping(value = "/upload",method = RequestMethod.POST)
        @ResponseBody
        public ApiResponse upload(@RequestParam("file")MultipartFile file) {
            return service.uploadImage(file, file.getOriginalFilename());//客户端会在FormData里面构造好名字 可以直接取出来
        }
}

Service实现图片提交到OSS

@RequestParam(“file”)说明客户端上传文件的key要是 “file”

@Service
public class UploadServiceImpl implements UploadService {

    @Override
    public ApiResponse uploadImage(MultipartFile file, String fileName) {
        ApiResponse apiResponse = new ApiResponse();
         try {
             // endpoint以杭州为例,其它region请按实际情况填写
            String endpoint = Constants.ALIYUN_OSS_ENDPOINT; 
            // accessKey请登录https://ak-console.aliyun.com/#/                                                                                                                                                                 查看
            String accessKeyId = Constants.ALIYUN_OSS_ACCESSKETID;
            String accessKeySecret = Constants.ALIYUN_OSS_ACCESSKEYSECRET;
            // 创建OSSClient实例
            OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
            // 上传
            InputStream inputStream = file.getInputStream();
            ossClient.putObject( Constants.ALIYUN_OSS_BUCKETNAME, fileName, inputStream);
            // 关闭client
            ossClient.shutdown();
            ImageResonseModel data = new ImageResonseModel();
            data.setImageUrl(Constants.ALIYUN_OSS_IMAGEURL_PRE+fileName);
            apiResponse.setData(data);
         } catch (Exception e) {
             e.printStackTrace();
             apiResponse.errorCode(ErrorCode.FAIL);
         }
        return apiResponse;
    }

上传成功的图片的URL = 阿里云后端的配置的域名+图片名称

图片地址:Constants.ALIYUN_OSS_IMAGEURL_PRE+fileName

PostMan来测试一下是否能接受到图片流
(以form-data的形式提交)
这里写图片描述

**如果有后台有报错:
可以把Header里面的Content-Type 删掉**

========postMan测试图片提交没问题之后 我们就可以让客户端来做测试了============

ios客户端代码:
使用AF的AFHTTPSessionManager里面的实例方法来提交图片

- (NSURLSessionDataTask *)POST:(NSString *)URLString
                    parameters:(id)parameters
     constructingBodyWithBlock:(void (^)(id <AFMultipartFormData> formData))block
                      progress:(nullable void (^)(NSProgress * _Nonnull))uploadProgress
                       success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
                       failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure

封装的AF请求预览:


    NSURLSessionTask *task = nil;

    @synchronized(self.manager) {
        self.manager.requestSerializer = [self requestJsonSerializerForModel:requestModel];

        switch (requestModel.HTTPMethod) {
            case DKHTTPMethodGet:
                task = [self.manager GET:url
                              parameters:dictParams
                                progress:nil
                                 success:successBlock
                                 failure:failedBlock];
                break;
            case DKHTTPMethodPost:
                task = [self.manager POST:url
                               parameters:dictParams
                                 progress:nil
                                  success:successBlock
                                  failure:failedBlock];
                break;
            case DKHTTPMethodPut:
                task = [self.manager PUT:url
                                   parameters:dictParams
                                      success:successBlock
                                      failure:failedBlock];
                break;
            case DKHTTPMethodDelete:
                task = [self.manager DELETE:url
                                      parameters:dictParams
                                         success:successBlock
                                         failure:failedBlock];
                break;
            case DKHTTPMethodMultipart: {
                task = [self.manager POST:url
                               parameters:dictParams
                constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
                    [dictParams enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
                        if ([obj isKindOfClass:[NSData class]]) {
                            [formData appendPartWithFileData:obj name:key fileName:[NSString stringWithFormat:@"%@.jpg", [[NSDate date] formatDateByFormatString:@"yyyy_MM_dd_HH_mm_ss_SSS"]] mimeType:@"image/jpeg"];
                        }
                    }];
                }progress:nil success:successBlock  failure:failedBlock];

            } break;
            default:
                DKAssert(0);
        }
    }

这里的构造的fileName就是SpringMVC后台得到的文件名(上面有提到)

[formData appendPartWithFileData:obj name:key fileName:[NSString stringWithFormat:@"%@.jpg", [[NSDate date] formatDateByFormatString:@"yyyy_MM_dd_HH_mm_ss_SSS"]] mimeType:@"image/jpeg"];

请求类:

@interface UploadImageHttpModel : WBRequestModel

@property (nonatomic,strong) NSData *file;

@end

上面的参数:
NSDictionary *dictParams = [requestModel toDictionary];

把图片作为流放在 param里面

这里写图片描述

测试结果完美!这里我就不截图了


多图上传

SpringMVC后台 就是把之前的file变成一个数组就可以了

Controller

   //上传图片
       @RequestMapping(value = "/upload",method = RequestMethod.POST)
        @ResponseBody
        public ApiResponse upload(@RequestParam("file") MultipartFile[] files) {
            return service.uploadImages(files);
        }

Service实现里面

@Override
    public ApiResponse uploadImages(MultipartFile[] files) {
        ApiResponse apiResponse = new ApiResponse();
        try {
             ArrayList<ImageResonseModel> list = new ArrayList<>();
            for (MultipartFile file : files) {

                if (!file.isEmpty()) {
                    String fileName = file.getOriginalFilename();
                    // endpoint以杭州为例,其它region请按实际情况填写
                    String endpoint = Constants.ALIYUN_OSS_ENDPOINT;
                    // accessKey请登录https://ak-console.aliyun.com/#/ 查看
                    String accessKeyId = Constants.ALIYUN_OSS_ACCESSKETID;
                    String accessKeySecret = Constants.ALIYUN_OSS_ACCESSKEYSECRET;
                    // 创建OSSClient实例
                    OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
                    // 上传
                    InputStream inputStream = file.getInputStream();
                    ossClient.putObject(Constants.ALIYUN_OSS_BUCKETNAME, fileName, inputStream);
                    // 关闭client
                    ossClient.shutdown();
                    ImageResonseModel data = new ImageResonseModel();
                    data.setImageUrl(Constants.ALIYUN_OSS_IMAGEURL_PRE + fileName);
                    list.add(data);
                }
            }
            apiResponse.setData(list);
        } catch (Exception e) {
            e.printStackTrace();
            apiResponse.errorCode(ErrorCode.FAIL);
        }
        return apiResponse;
    }

postMan测试多图:
这里写图片描述

debug后台调试

这里写图片描述

接下来是IOS这块的修改:
请求类

@interface UploadImageHttpModel : WBRequestModel

@property (nonatomic,strong) NSArray <NSData *>*file;

@end

对应AF封装的的请求框架的修改(局部代码)

case DKHTTPMethodMultipart: {
                task = [self.manager POST:url
                               parameters:dictParams
                constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
                    [dictParams enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
                        //多文件 file是NSData的数组
                        if ([obj isKindOfClass:[NSArray class]]) {
                            for (id data in obj) {
                                if ([data isKindOfClass:[NSData class]]) {
                                    [formData appendPartWithFileData:data name:key fileName:[NSString stringWithFormat:@"%@.jpg", [[NSDate date] formatDateByFormatString:@"yyyy_MM_dd_HH_mm_ss_SSS"]] mimeType:@"image/jpeg"];
                                }
                            }
                        }else//单文件 file是NSData对象
                        {
                            if ([obj isKindOfClass:[NSData class]]) {
                                [formData appendPartWithFileData:obj name:key fileName:[NSString stringWithFormat:@"%@.jpg", [[NSDate date] formatDateByFormatString:@"yyyy_MM_dd_HH_mm_ss_SSS"]] mimeType:@"image/jpeg"];
                            }
                        }
                    }];
                }progress:nil success:successBlock  failure:failedBlock];

ios调试结果:
这里写图片描述

同样的Spring的Controller里面也是接受到了两个文件(如图)

这里写图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值